#include <iostream>
struct ABC{
int A;
ABC(int i = 1) : A(i) {}
~ABC() {
std::cout << A << std::endl;
}
void destruct() {
delete this;
}
};
int main() {
ABC A1(2);
A1.destruct();
return 0;
}
Output:
2
2在这段代码中,我试图手动删除结构变量。这样做,我意识到破坏者在这里被打了两次电话。为什么会发生这种情况?为什么在调用destruct()时不删除它?
发布于 2016-05-25 09:52:02
delete this调用会导致未定义行为,这意味着任何事情都可能发生。
delete只能用于new创建的对象。
对于具有非平凡析构函数(例如A1)的自动对象,除非在作用域结束之前在同一位置创建另一个ABC,否则不可能“尽早销毁它们”。换句话说,您不能“关闭”范围结束时发生的销毁过程。
发布于 2016-05-25 09:55:04
这是RAII在工作加上你在一个物体上自杀。调用对象上的析构函数几乎总是错误的!两次调用析构函数总是错误的,因为它会调用未定义的行为。
您必须理解C++正在为您处理内存,如果您只是让它:
struct Foo{};
int main() {
Foo f; // automatic storage, gets destroyed
// when object gets out of scope
Foo* g = new Foo(); // heap allocated
delete g; // only here you have to delete
}请记住:不要通过delete创建任何您没有通过new创建的东西(感谢Mike的评论)。并且,除非需要,否则不要使用(裸)堆分配。
发布于 2016-05-25 09:59:35
为什么调用
destruct()时不删除我的对象?
当对象在C++中被销毁时,并不意味着该对象会消失。这意味着执行析构函数中的清理代码,并且从该点开始对对象成员的任何访问都是无效的。
当您调用destruct()时,您尝试通过调用delete来释放对象的内存。这本身就是未定义的行为,因为您没有用new分配对象。此调用将导致第一次打印输出。
但是,由于对象位于自动内存中,因此当对象超出作用域时,C++必须调用其析构函数。这是导致第二次打印输出的调用。
注意:您可以通过在动态内存中分配A1来修复代码:
int main() {
ABC *A1 = new ABC(2);
A1->destruct();
return 0;
}现在只有一个打印输出(演示)。但是,在成员函数中隐藏delete的做法是值得怀疑的。
https://stackoverflow.com/questions/37433495
复制相似问题