首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么destructor在这里被叫了两次?

为什么destructor在这里被叫了两次?
EN

Stack Overflow用户
提问于 2016-05-25 09:49:34
回答 4查看 415关注 0票数 0
代码语言:javascript
复制
#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()时不删除它?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-05-25 09:52:02

delete this调用会导致未定义行为,这意味着任何事情都可能发生。

delete只能用于new创建的对象。

对于具有非平凡析构函数(例如A1)的自动对象,除非在作用域结束之前在同一位置创建另一个ABC,否则不可能“尽早销毁它们”。换句话说,您不能“关闭”范围结束时发生的销毁过程。

票数 6
EN

Stack Overflow用户

发布于 2016-05-25 09:55:04

这是RAII在工作加上你在一个物体上自杀。调用对象上的析构函数几乎总是错误的!两次调用析构函数总是错误的,因为它会调用未定义的行为。

您必须理解C++正在为您处理内存,如果您只是让它:

代码语言:javascript
复制
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的评论)。并且,除非需要,否则不要使用(裸)堆分配。

票数 2
EN

Stack Overflow用户

发布于 2016-05-25 09:59:35

为什么调用destruct()时不删除我的对象?

当对象在C++中被销毁时,并不意味着该对象会消失。这意味着执行析构函数中的清理代码,并且从该点开始对对象成员的任何访问都是无效的。

当您调用destruct()时,您尝试通过调用delete来释放对象的内存。这本身就是未定义的行为,因为您没有用new分配对象。此调用将导致第一次打印输出。

但是,由于对象位于自动内存中,因此当对象超出作用域时,C++必须调用其析构函数。这是导致第二次打印输出的调用。

注意:您可以通过在动态内存中分配A1来修复代码:

代码语言:javascript
复制
int main() {
    ABC *A1 = new ABC(2);
    A1->destruct();
    return 0;
}

现在只有一个打印输出(演示)。但是,在成员函数中隐藏delete的做法是值得怀疑的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37433495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档