在退出范围或删除等过程中调用析构函数。其目的是将动态分配的资源返回到池中。当我显式调用析构函数(空析构函数)时,它将/对类成员有什么作用?
这不是寻求调试帮助的问题, 示例代码:
class Z(){
public:
Z(){ };
~Z(){ };
int count {0};
}
void main()
{
Z* z = new Z();
z->count = 1;
z->~Z();
cout << z->count << endl;
}
在我看来,z-> count在测试期间调用析构函数后仍然有效。显式调用析构函数不会将对象的资源返回到堆。我想仔细检查这是否是预期的行为
我猜直接调用析构函数z->〜Z()与“删除z”不同,一个只会执行在〜Z()中实现的内容,以后将执行〜Z()然后删除该类成员。 / p>
答案 0 :(得分:6)
析构函数只是要在将类的内存返回到堆或堆栈之前执行的一段代码。它本身不会取消分配该类使用的内存,但是应使用它来清理您可能在构造函数中完成的所有分配。
如果通过new创建了类,则应直接调用delete而不是析构函数。删除将为您调用析构函数后,将类的内存返回到堆中。
答案 1 :(得分:3)
指针123px
指向的内存将“保持活动”,尽管一旦破坏了相应的key
对象,您可能会失去与其的任何关系。因此,您正在此处泄漏内存。为避免这种情况,请添加析构函数,即Z
。
一旦拥有对象被破坏,就不能访问~Z() { delete[] key; }
的成员,即Z
和key
的成员。这些数据成员的“值”可能不是“超出系统内存的范围”,但是您不能再访问它们。
关于通过count
调用析构函数:这是非常不寻常的,并且很可能是错误的,除非您打算自己管理内存并且非常了解自己在做什么。
通常,即在您编码的所有情况下,大约99.9999%,析构函数都应在生命周期结束时要被销毁的对象隐式触发,例如,对于超出范围的自动变量和在超出范围时的动态分配对象显式调用z->~Z()
。
因此,程序的(稍微)更好的版本是:
delete z
这只是“稍微”好一点,因为当复制或移动class Z {
public:
Z(){ key = new char[10]; }
~Z(){ delete[] key; }
char* key;
int count {0};
};
int main() {
Z* z = new Z();
z->count = 1;
z->key[0] = 'K';
delete z;
}
对象时,该类仍不覆盖(当您自己分配内存时,请参阅3/5规则)。
所以我建议按照以下方式进行操作:
Z
答案 2 :(得分:-1)
对于每个 new ,应该有 delete 。
您正在构造函数中的堆上手动分配内存块。因此,您必须手动将其删除:
Class Z(){
public:
char* key;
int count {0};
Z(){
key = new char[10];
};
~Z(){
delete[] key;
};