c++,析构函数会破坏class成员吗?
c++, will destructor destruct class member?
析构函数在作用域退出或删除等过程中被调用。它旨在 return 动态分配资源到池中。当我显式调用析构函数(空析构函数)时,它/它会对 class 成员做什么?
这不是寻求帮助调试的问题,
示例代码:
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 在我的测试期间在析构函数调用后仍然存在。显式调用析构函数不会 return 堆对象的资源。我想仔细检查这是否是预期的行为
我猜直接调用析构函数 z->~Z() 与 "delete z" 不同,一个只会执行在 ~Z() 中实现的,稍后会执行 ~Z() 然后删除 class 成员。
For every new, there should be delete.
您正在构造函数中的堆上手动分配内存块。因此,您必须手动删除它:
Class Z(){
public:
char* key;
int count {0};
Z(){
key = new char[10];
};
~Z(){
delete[] key;
};
指针key
指向的内存将"stay alive",尽管一旦相应的Z
-对象被销毁,您可能会失去与它的任何关系。所以你在这里泄漏内存。为避免这种情况,请添加一个析构函数,即 ~Z() { delete[] key; }
.
Z
的成员,即 key
和 count
,一旦拥有的对象被销毁,则不得访问。可能是这些数据成员的"values"不是"cuttet out of system's memory",但是你不能再访问它们了。
关于通过 z->~Z()
调用析构函数:这是非常不寻常的,而且很可能是错误的,除非您打算自己管理内存并且非常清楚自己在做什么。
通常,即在您编码的所有情况下,大约 99.9999% 的情况下,只要对象在其生命周期结束时要被销毁,析构函数就会被隐式触发,即超出范围时的自动变量和动态分配显式调用 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;
}
它只是 "slightly" 更好,因为 class 仍然不覆盖复制或移动 Z
对象(在分配内存时查看 3/5 规则你自己的)。
所以我建议按以下方式进行:
#include <string>
class Z {
public:
std::string key;
int count {0};
};
int main() {
Z z;
z.count = 1;
z.key = "K";
}
析构函数只是在 class 的内存 return 到堆或堆栈之前要执行的一段代码。它本身不会取消分配 class 使用的内存,但应该用于清理您可能在构造函数中完成的任何分配。
如果您通过 new 创建了 class,您应该调用 delete 而不是直接调用析构函数。在为您调用析构函数后,delete 将 return class 的内存放到堆中。
析构函数在作用域退出或删除等过程中被调用。它旨在 return 动态分配资源到池中。当我显式调用析构函数(空析构函数)时,它/它会对 class 成员做什么?
这不是寻求帮助调试的问题, 示例代码:
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 在我的测试期间在析构函数调用后仍然存在。显式调用析构函数不会 return 堆对象的资源。我想仔细检查这是否是预期的行为
我猜直接调用析构函数 z->~Z() 与 "delete z" 不同,一个只会执行在 ~Z() 中实现的,稍后会执行 ~Z() 然后删除 class 成员。
For every new, there should be delete.
您正在构造函数中的堆上手动分配内存块。因此,您必须手动删除它:
Class Z(){
public:
char* key;
int count {0};
Z(){
key = new char[10];
};
~Z(){
delete[] key;
};
指针key
指向的内存将"stay alive",尽管一旦相应的Z
-对象被销毁,您可能会失去与它的任何关系。所以你在这里泄漏内存。为避免这种情况,请添加一个析构函数,即 ~Z() { delete[] key; }
.
Z
的成员,即 key
和 count
,一旦拥有的对象被销毁,则不得访问。可能是这些数据成员的"values"不是"cuttet out of system's memory",但是你不能再访问它们了。
关于通过 z->~Z()
调用析构函数:这是非常不寻常的,而且很可能是错误的,除非您打算自己管理内存并且非常清楚自己在做什么。
通常,即在您编码的所有情况下,大约 99.9999% 的情况下,只要对象在其生命周期结束时要被销毁,析构函数就会被隐式触发,即超出范围时的自动变量和动态分配显式调用 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;
}
它只是 "slightly" 更好,因为 class 仍然不覆盖复制或移动 Z
对象(在分配内存时查看 3/5 规则你自己的)。
所以我建议按以下方式进行:
#include <string>
class Z {
public:
std::string key;
int count {0};
};
int main() {
Z z;
z.count = 1;
z.key = "K";
}
析构函数只是在 class 的内存 return 到堆或堆栈之前要执行的一段代码。它本身不会取消分配 class 使用的内存,但应该用于清理您可能在构造函数中完成的任何分配。
如果您通过 new 创建了 class,您应该调用 delete 而不是直接调用析构函数。在为您调用析构函数后,delete 将 return class 的内存放到堆中。