【问题标题】:Order of the destructor calls at the end of block\program [duplicate]块\程序末尾的析构函数调用顺序[重复]
【发布时间】:2013-06-21 23:47:31
【问题描述】:

因此,在块\程序的末尾,编译器调用它自己的析构函数来定义对象。调用析构函数有特定的顺序吗?

class Foo1{
public:
~Foo1 () {cout << "Foo1 DTOR" << endl;}
};
class Foo2{
public:
~Foo2 () {cout << "Foo2 DTOR" << endl;}
};
void main(){
Foo1 A;
Foo2 B;
}

运行这个程序我得到了输出:

Foo2 DTOR

Foo1 DTOR

它是否总是从最后一个定义的对象开始并以第一个对象结束?或者这种行为无法预测,而我的输出是针对这种情况的?

【问题讨论】:

  • 是的,事情通常是这样运作的。例外情况是一个只能在一个方向上遍历的集合(例如,单链表),在这种情况下,它包含的对象会按照它们的创建顺序被销毁。
  • 为什么调用它们的顺序很重要?这只是好奇吗?
  • 多个重复:搜索 [:C++] 析构函数顺序
  • 这就是你观察到的栈式内存的LIFO原理。
  • @Pixelchemist 这也是我的假设,但不确定,不幸的是没有花足够的时间在谷歌上搜索更多问题(或 mb 谷歌搜索错误)

标签: c++ destructor


【解决方案1】:

析构函数总是以与构造函数相反的顺序运行(动态内存除外,其中程序员显式删除内存中的对象(调用它的析构函数)。

在您的示例中,A 位于 B 之前,因此它是前面调用的构造函数。这就是为什么在 B 的析构函数之后调用它的析构函数。

【讨论】:

    【解决方案2】:

    对象生命周期的 LIFO 排序是唯一有意义的事情。考虑这个具有中等代表性的例子:

    struct ValueHolder
    {
        int value;
        ValueHolder() : value(0) { }
        ~ValueHolder() { std::cout << "Value = " << value << "\n"; }
    };
    
    struct HolderGuard
    {
        ValueHolder & h;
        HolderGuard(ValueHolder & vh) : vh(h) { }
        ~HolderGuard() { ++h.value; }
    };
    

    用法:

    int main()
    {
        ValueHolder h;
        HolderGuard(h);
    }
    

    这将首先增加保存的值,然后打印它。如果后面的东西不先被销毁,后面的东西就不可能依赖前面的东西。

    (示例构造的美妙之处在于,即使后面的代码抛出异常,它也会做正确的事情。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-08
      • 2013-06-24
      • 2012-05-22
      • 1970-01-01
      • 2020-10-14
      • 2020-04-08
      相关资源
      最近更新 更多