mhy*_*mhy 1 c++ memory constructor destructor
我有一个关于在C++中正确删除/释放内存的问题.
假设我有以下...(假设A,B,C,D是类.B和C有实例变量A* a.D有两个实例变量,B* b和C* c)
A* a = new A();
B* b = new B(a);
C* c = new C(a);
D* d = new D(b, c);
Run Code Online (Sandbox Code Playgroud)
B和C的析构函数:
B::~B() { delete a; }
C::~C() { delete a; }
Run Code Online (Sandbox Code Playgroud)
D的析构函数:
D::~D() { delete b; delete c; }
Run Code Online (Sandbox Code Playgroud)
现在我打电话的时候
delete d;
Run Code Online (Sandbox Code Playgroud)
我得到一个"访问冲突读取位置0xfeeefeee"(我在Visual Studio 2010中).我想这是因为
- 已经解除分配D的析构函数试图"删除"相同的内存(a)两次a.
- 我有两个指针(一个在B另一个中C)指向同一个地址(of a),当D的析构函数删除b(反过来调用delete a)时,此内存现在设置为已释放.
- 当D析构函数删除时c,c尝试自己调用delete a失败,因为a已经解除分配.
我对C++比较陌生,但对编程并不陌生.我查了一下,看到智能指针(如shared_ptr)可以解决这个问题,但在这种情况下最好的做法是什么?我应该创建两个单独的A对象吗?
如果您的设计计划将共享同一个a既b和c,你应该封装在一个指针共享指针.
但是,在某些情况下,只需要使用指针.在大多数情况下,参考也可以完成这项工作.在您的情况下,如果您定义这四个实例的上下文也应限制其生命周期,只需将它们定义为值:
A a;
B b(a);
C c(a);
D d(b, c);
Run Code Online (Sandbox Code Playgroud)
要通过引用传递对象,请在构造函数和私有成员中使用引用类型.并且不要delete在他们的析构函数中调用.
class B {
A & m_a;
public:
B (A &a) : m_a(a) {
}
};
Run Code Online (Sandbox Code Playgroud)
关于引用和指针的一个非常重要的区别(开头可能比你想象的要多)是你不能改变引用(只有引用的值).此外(这是这个事实的含义),必须在定义变量时分配它.这就是为什么你必须:m_a(a)在构造函数中使用奇怪的初始化语法()而不是在它的主体中使用赋值(m_a = a不起作用).
此外,永远不要删除在构造函数中传递的析构函数中的实例,除非您知道自己在做什么,这意味着您知道三个规则.但智能指针使这个过时了.