2

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.

Digvijaysinh Gohil
  • 1,367
  • 2
  • 15
  • 30
user156262
  • 37
  • 2
  • 8

3 Answers3

4

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.

Jodocus
  • 7,493
  • 1
  • 29
  • 45
  • So, it is aaa, aa, a. Right? – user156262 Nov 24 '17 at 09:16
  • @user156262 Yes, as I wrote. You can check it yourself using e.g. a debugger. – Jodocus Nov 24 '17 at 09:17
  • And the order of declaration is a, aa, aa because we have A a, aa, aaa. Is this why the order of constructor calls for A is a, aa, aaa and not for example, aa, a, aaa? – user156262 Nov 24 '17 at 09:22
  • 1
    @user156262 You were given an answer. And a rather good one. If you have other questions then please post new questions. – Ron Nov 24 '17 at 09:24
3

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; }
     ^
Arash
  • 2,114
  • 11
  • 16
  • And the order of declaration is a, aa, aa because we have A a, aa, aaa. Is this why the order of constructor calls for A is a, aa, aaa and not for example, aa, a, aaa? – user156262 Nov 24 '17 at 09:23
  • 1
    @user156262, run gcc compiler or what ever with all warning checks turned on. You realize that it warns you. This order following is a standard. I refer you to [this post](https://stackoverflow.com/a/24287946/8911468). – Arash Nov 24 '17 at 09:36
1

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.

Community
  • 1
  • 1
lockcmpxchg8b
  • 2,205
  • 10
  • 16