简体   繁体   English

对象数组的销毁顺序

[英]Order of destruction for Array of Objects

class MyClass
{
};

void foo
{
    MyClass arr[10]; 
}

I want to know the order of destruction of array objects when function returns. 我想知道函数返回时数组对象的破坏顺序。

I read it More Effective C++ about it and it says that destructor are invoked in reverse order to that of constructor order as follows: 我读了它更有效的C ++,它说析构函数的调用顺序与构造函数顺序相反,如下所示:

for(int i = 9 ; i >= 0 ;i--)
{
    arr[i].MyClass::~MyClass();
}

Can anybody tell me the reason for it ? 谁能告诉我它的原因?

That's continuation of reverse order of destructor invokation filosophy of C++. 这是C ++的析构函数invokation filosophy的逆序的延续。 When stack-allocated objects are destroyed it is done in reverse order to facilitate RAII. 当堆栈分配的对象被销毁时,它以相反的顺序完成以促进RAII。 Although that is not really necessary for array elements (they are all constructed with the default constructors and any order of construction/destruction would do) the same is done with them just for consistency. 虽然这对于数组元素来说并不是必需的(它们都是使用默认构造函数构造的,并且任何构造/销毁的顺序都可以),但为了保持一致性,它们也是如此。

The information you're referring to in More Effective C++ applies to objects that contain a couple of other object, as in this case: 您在更有效的C ++中引用的信息适用于包含其他几个对象的对象,如下例所示:

class Foo {
  private:
     Bar bar_1;
     Bar bar_2;

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

In the above example, you'll have bar_1 constructed first, followed by bar_2. 在上面的示例中,您将首先构建bar_1,然后是bar_2。 When an object of class Foo then gets destroyed, bar_2 gets destroyed first, then bar_1 . 当类Foo的对象被破坏时, bar_2被销毁,然后是bar_1 That is what Scott Meyers is referring to. 这就是斯科特迈耶斯所指的。

From the point of view of the class, an array of bars would be another object that the compiler needs to destroy, so the order of destruction affects when the array gets destructed in the context of the other objects in the class. 从类的角度来看,一个条形数组将是编译器需要销毁的另一个对象,因此破坏的顺序会影响数组在类中其他对象的上下文中被破坏的时间。

As to which order the elements of an array get destroyed, I wouldn't be too surprised if that is implementation dependent. 至于数组元素被破坏的顺序,如果这是依赖于实现的话,我不会太惊讶。 You'll also have optimisation playing a role here (for example, a POD array can be destroyed just by freeing its memory, as can be an object that is solely composed of PODs). 您还将在此处进行优化(例如,可以通过释放其内存来销毁POD阵列,因为可以是仅由POD组成的对象)。 All of the above can affect the order in which the elements of an array will be destroyed. 以上所有都会影响数组元素的销毁顺序。

I'd be interested to see why you do need to know the order in which the array elements are destroyed (apart from technical curiosity, which would be a valid reason IMHO). 我很想知道你为什么需要知道数组元素被破坏的顺序(除了技术好奇,这是恕我直言的正当理由)。 If it is because there are dependencies between the elements of the array, I think the data structure might need reviewing. 如果是因为数组元素之间存在依赖关系,我认为数据结构可能需要进行审核。

Any order would do, really. 任何订单都可以。 The two obvious choices are of course in order or in reverse order. 两个显而易见的选择当然是按顺序或相反顺序。 However, in this case none of the compiler makers thought it would be worthwhile to leave this implementation-dependent. 但是,在这种情况下,没有一个编译器制造商认为保留这种依赖于实现的方法是值得的。 Hence, the choice was made to mandate the reverse order (as sharptooth stated, extending the usual LIFO behavior) 因此,选择强制执行相反的顺序(如同尖锐的说法,延伸通常的LIFO行为)

Perhaps the order in which the objects that make up the array are placed on the stack. 也许组成数组的对象放在堆栈中的顺序。 Anyway, except curiosity, I can think of no reason to worry about the destruction order. 无论如何,除了好奇心,我认为没有理由担心破坏秩序。

You don't cite which page in Meyer's book you are referring to, but I agree with Timo Geusch that the explanation sounds like it is referring to the that constructors and destructors are invoked according to the inheritance. 你没有引用你所指的Meyer书中的哪一页,但我同意Timo Geusch的说法听起来好像是指的是根据继承调用构造函数和析构函数。

For an array of object instances, the order that objects are destroyed is the inverse of the order of construction. 对于对象实例数组,对象被销毁的顺序是构造顺序的倒数。 This is easy to verify, as the following code shows. 这很容易验证,如下面的代码所示。 A class variable keeps track of the total number of instances created, and a data member for each object keeps track of its own number. 类变量跟踪创建的实例总数,每个对象的数据成员跟踪其自己的编号。 The constructor and destructor print a message, so when run we can see exactly what happens and when. 构造函数和析构函数会打印一条消息,因此在运行时我们可以确切地看到发生了什么以及何时发生。

The test code prints out the count of objects from 0 to 9 when constructing, then from 9 down to 0 when destructing the instances. 测试代码在构造时打印出从0到9的对象计数,然后在破坏实例时从9向下打印到0。 (This was tested with g++-4.2 on Mac OS X.) (这是在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;
}

You would need to check the C++ Standard, as I'm not 100% sure that this is not an implementation detail (as is often the case), in which case you don't want to rely on this behaviour. 您需要检查C ++标准,因为我不是100%确定这不是实现细节(通常是这种情况),在这种情况下您不希望依赖此行为。

Note also that it is not so common to create a stack-based array of actual object instances. 另请注意,创建基于堆栈的实际对象实例数组并不常见。 You are more likely to be using std::vector , or maybe using smart pointers to heap-allocated objects. 您更可能使用std::vector ,或者使用智能指针来堆分配对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM