对象数组的销毁顺序

5
class MyClass
{
};

void foo
{
    MyClass arr[10]; 
}

我想了解函数返回时数组对象销毁的顺序。
我读了《More Effective C++》,它说析构函数的调用顺序与构造函数相反,具体如下:
for(int i = 9 ; i >= 0 ;i--)
{
    arr[i].MyClass::~MyClass();
}

有人能告诉我这是为什么吗?(涉及IT技术)
5个回答

4

这是C++反向析构调用哲学的延续。当栈中分配的对象被销毁时,它们会按照相反的顺序进行销毁,以方便RAII。尽管这对于数组元素来说并不是必要的(它们都是使用默认构造函数构建的,任何构建/销毁顺序都可以),但为了保持一致性,也会按照相同的方式处理它们。


4
它们都是使用默认构造函数构建的,任何构造/析构顺序都可以。由于无参构造函数可以访问全局变量(例如类静态变量),因此构造它们的顺序对得到的数组有影响。所以我不太确定你所说的“任何顺序都可以”的意思 - 只有一个顺序符合标准12.6。标准本可以规定顺序是实现定义的,或者可以规定它们按索引中不同质因数数量的逆序构造,平局则根据7进制下的数字总和决定;-) - Steve Jessop

2

在《More Effective C++》中提到的信息适用于包含其他对象的对象,就像这个例子:

class Foo {
  private:
     Bar bar_1;
     Bar bar_2;

  public:
     Foo() : bar_1(), bar_2() {}
};

在上面的示例中,你将首先构建bar_1,然后是bar_2。当类Foo的对象被销毁时,bar_2会先被销毁,然后是bar_1。这就是Scott Meyers所指的。
从类的角度来看,bar数组将是编译器需要销毁的另一个对象,因此销毁顺序影响数组在类中其他对象的上下文中何时被销毁。
至于数组元素的销毁顺序,如果这是与实现相关的,我不会感到太惊讶。优化也在这里发挥作用(例如,POD数组可以通过释放其内存来销毁,仅由POD组成的对象也可以这样)。所有这些都可能影响数组元素被销毁的顺序。
我很想知道为什么你需要知道数组元素被销毁的顺序(除了技术好奇心外,这是一个有效的理由)。如果是因为数组元素之间存在依赖关系,我认为数据结构可能需要重新审查。

1

其实任何顺序都可以。显而易见的选择当然是按顺序或按相反顺序。然而,在这种情况下,编译器制造商都认为没有必要留下这个实现依赖项。因此,选择强制使用相反的顺序(如sharptooth所述,扩展了通常的LIFO行为)。


0

您没有说明Meyer的书中是哪一页,但我同意Timo Geusch的观点,解释似乎是在指出构造函数和析构函数是根据继承调用的。

对于对象实例数组,对象销毁的顺序与构造的顺序相反。这很容易验证,如下面的代码所示。一个类变量跟踪创建的实例总数,每个对象的数据成员跟踪其自己的编号。构造函数和析构函数打印一条消息,因此当运行时我们可以看到发生了什么以及何时发生。

测试代码在构造时从0到9打印对象计数,然后在销毁实例时从9到0递减。(在Mac OS X上使用g++-4.2进行了测试。)

#include <iostream>

class MyClass
{
public:

    MyClass()
    {
        mCounter = kInstanceCount++;
        std::cout << "+++ MyClass() " << mCounter << std::endl;
    }

    ~MyClass()
    {
        std::cout << "--- MyClass() " << mCounter << std::endl;
    }

private:
    unsigned            mCounter;
    static unsigned     kInstanceCount;
};

unsigned MyClass::kInstanceCount = 0;

int main()
{
    MyClass arr[10];
    return 0;
}

你需要检查C++标准,因为我不能百分之百确定这不是一个实现细节(通常情况下是这样),如果是这种情况,你就不应该依赖这种行为。

还要注意的是,创建基于堆栈的实际对象实例数组并不常见。你更可能使用std::vector,或者使用智能指针来分配堆内存中的对象。


-1
也许是构成数组的对象在堆栈上放置的顺序。无论如何,除了好奇心,我想不到任何理由去担心销毁顺序。

如果arr[n]在其DTor中引用了元素arr[n+1],那么你可能会遇到麻烦。然而,就我目前的想法而言,我无法想到一个真实世界的情况,需要这样做。 - foraidt
@mxp。完全同意,但如果数组的每个元素都依赖于该数组中至少一个元素,那么该数组元素的销毁顺序仅是一个小问题。 - jrbjazz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接