user156262
user156262

Reputation: 35

C++ - Destructor call order

I have the following C++ code:

#include <iostream>
struct A 
{
    A() { std::cout << "A" << ++x; }
    A(int x) : A() { std::cout << x; }
    ~A() { std::cout << "D"; }
    static int x;
};

int A::x = 0;
struct B 
{
    A a, aa, aaa;
    B() : aa(1), a(2) { std::cout << "B" << std::endl; }
    ~B() { std::cout << "B" << A::x; }
};
B beta;

    int main()
    {
        return 0;
    }

I understand everything in the control flow except of destructor calls. Here is the control flow without destructors:

  1. create object B

  2. call constructor B call a,aa,aaa respectively

2.1 for a, call A(int x)

2.2 for aa, call A(int x)

2.3 for aaa, call A()

  1. display B from B c-tor body

Now the 4. step is to call destructor B, I know that.

What I don't know is what is the order of calling destructors for A. Is it a,aa,aaa respectively, or aaa,aa,a respectively?

Thanks in advance.

Upvotes: 2

Views: 3488

Answers (3)

lockcmpxchg8b
lockcmpxchg8b

Reputation: 2303

This took forever to find, but per n4659 (ISO C++17 draft):

15.6.2 Initializing bases and members

paragraph (13.3)

Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]

Here, mem-initializers are the list following the colon in the constructor definition.

Upvotes: 1

Arash
Arash

Reputation: 2164

Everything looks fine. It constructs-destructs stack-wise (First in/Last out):

#include <iostream>
struct A 
{
    A() { name="untitled"; std::cout << name <<" constructor" << std::endl; }
    A(std::string name):name(name) { std::cout << name <<" constructor" << std::endl; }
    ~A() { std::cout << name <<" destructor" << std::endl; }
    std::string name;
};

struct B 
{
    A a, aa, aaa;
    B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
    ~B() { std::cout << "B destructor" << std::endl; }
};
B beta;

int main()
{
    return 0;
}

Result:

a constructor
aa constructor
untitled constructor
B constructor
B destructor
untitled destructor
aa destructor
a destructor

Is this order guaranteed? yes


If you turn on all the warnings you see this:

 g++ -Wall -Wreorder main.cpp 


main.cpp: In constructor ‘B::B()’:
main.cpp:12:10: warning: ‘B::aa’ will be initialized after [-Wreorder]
     A a, aa, aaa;
          ^
main.cpp:12:7: warning:   ‘A B::a’ [-Wreorder]
     A a, aa, aaa;
       ^
main.cpp:13:5: warning:   when initialized here [-Wreorder]
     B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
     ^

Upvotes: 3

Jodocus
Jodocus

Reputation: 7581

The member objects get destroyed in the reversed order they got constructed. Note that you do not influence this order by changing the order in the constructor's initialization list. The order is exclusively determined by the order you declare them in the struct/class definition.

What I don't know is what is the order of calling destructors for A. Is it a,aa,aaa respectively, or aaa,aa,a respectively?

Thus, the latter case is happening.

Upvotes: 4

Related Questions