C++ C+中的递归析构函数+;
假设我有一个类似于以下内容的类:C++ C+中的递归析构函数+;,c++,memory-leaks,destructor,C++,Memory Leaks,Destructor,假设我有一个类似于以下内容的类: #include <vector> class element { public: element(); ~element(); virtual void my_func(); private: std::vector<element*> _elements; }; 另外,如果我这样做(也就是不要使用new): 从析构函数调用delete this(这就是destroy()所做的)总是错误的,因为析构函数是
#include <vector>
class element
{
public:
element();
~element();
virtual void my_func();
private:
std::vector<element*> _elements;
};
另外,如果我这样做(也就是不要使用new
):
从析构函数调用delete this
(这就是destroy()
所做的)总是错误的,因为析构函数是在删除当前对象时调用的
这将是一个问题,因为
e1_1
将在调用其析构函数时自动销毁。由于这会调用destroy()
,在未使用new
分配的对象上调用delete this
,因此会导致未定义的行为。(如果幸运的话,它会立刻炸到你的脸上。)
最好从析构函数中删除删除此
,只让析构函数删除对象向量中的对象:
for(std::vector<element*>::size_type i = 0; i < _elements.size(); ++i)
delete _elements[i];
检查指针的NULL
ness是不必要的,因为delete
被定义为在传递给它的指针为NULL
时不执行任何操作
element::~element()
{
typedef std::vector<element*>::const_iterator iterator;
for (iterator it(_elements.begin()); it != _elements.end(); ++it)
delete *it;
}
当元素
被销毁时,其\u元素
容器将自动销毁。当容器被销毁时,它将销毁其每个元素。std::unique_ptr
拥有它指向的对象,当std::unique_ptr
被销毁时,它将销毁它指向的元素
通过在这里使用std::vector
,您不需要提供自己的析构函数,因为所有这些内置功能都会为您进行清理
如果您希望能够复制元素
树,您仍然需要提供自己的复制构造函数和复制分配操作符来克隆树。但是,如果不需要树是可复制的,则不需要像自己管理内存那样声明复制操作:std::unique_ptr
容器本身是不可复制的,因此它作为成员变量的存在将抑制隐式生成的复制操作
删除此
不应该在那里,因为根据定义,该对象已经处于销毁状态元素
,则其成员向量
中的所有指针也将被复制;然后,当原始指针超出范围时,它们的指针将被销毁,并且元素
副本有一个悬挂指针的向量
。您需要一个复制运算符和赋值运算符元素
s对象本身
#include <vector>
class element
{
public:
void add_element(element const& e) {
_elements.push_back(e);
}
private:
std::vector<element> _elements;
};
#包括
类元素
{
公众:
无效添加元素(元素常量和e){
_元素。推回(e);
}
私人:
std::矢量元素;
};
如果您以前多次引用同一
元素
进入其他不同的元素
,这将微妙地改变您的程序,但您必须自己决定是否需要这种混乱的依赖关系。不,这样做行不通。您永远不会删除此。你就是不知道。基本上,去掉销毁方法,将所有内容放入~element()
中,除了删除此部分。而不是调用destroy方法,只需delete_元素[i]
您可以调用delete\u元素。在(i)
中,您不应该测试在析构函数中该是否为空。它不能为空。调用是否会删除\u元素。at(i)
是否会正确处理所有子元素?换句话说,它们是否会按正确的顺序(从下到上)进行处理?因为我认为如果我删除一个元素
,它的\u元素
,那将是一个漏洞
调用某物的类的析构函数,然后释放指针。应尽可能避免使用原始指针。在这种情况下:确保您确实需要一个指针向量(通常仅当元素
是抽象基类或不可复制时才需要),如果是这样,请选择ptr_向量
@Philipp:在这种情况下,需要一个指针容器:不能用不完整的类型实例化标准库容器,因此,元素
不能将std::vector
作为成员。(或者,你可以使用第三方容器库。Boost有一个容器库,它的实例化要求不那么严格。)那么,在这种情况下,你能把delete*it
看作是对~元素
的递归调用吗?@Eric:实际上,删除一个对象会首先调用对象的析构函数(它应该清理它所负责的一切),然后释放对象占用的内存。最后一段是误导性的;if
从来都不是必需的,而不是整个片段(当然,作为相关说明,删除这个很少有用!)@Lightness:我正在改进它。:)
感谢您的评论--我之所以需要使用指针,是因为元素
是一个具有虚拟
函数的基类。这是确保执行正确形式的虚拟函数的唯一方法。@Eric:OK;那可能是有道理的。不过,还是考虑一个包装的指针实现,比如<代码> STD::SysDypPTR < /C> >代码>删除此;code>是有效的,偶尔也有用。是的,但你仍然从来没有做过,就像你从来没有做过某些其他事情一样,你有时会因为方便而最终做这些事情。
class element
{
public:
element();
~element();
private:
std::vector<element*> _elements;
};
element::~element()
{
destroy();
}
for(int i = 0; i < _elements.size(); ++i)
_elements.at(i)->destroy();
element el_1;
for(std::vector<element*>::size_type i = 0; i < _elements.size(); ++i)
delete _elements[i];
if(this != NULL)
delete this;
element::~element()
{
typedef std::vector<element*>::const_iterator iterator;
for (iterator it(_elements.begin()); it != _elements.end(); ++it)
delete *it;
}
std::vector<std::unique_ptr<element>> _elements;
#include <vector>
class element
{
public:
void add_element(element const& e) {
_elements.push_back(e);
}
private:
std::vector<element> _elements;
};