简体   繁体   中英

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:

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++. When stack-allocated objects are destroyed it is done in reverse order to facilitate 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:

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. When an object of class Foo then gets destroyed, bar_2 gets destroyed first, then 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). 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)

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.

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. (This was tested with g++-4.2 on Mac OS X.)

#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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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