What is the order of evaluation in a member initializer list?
Asked Answered
Z

4

299

I have a constructor that takes some arguments. I had assumed that they were initialized in the order listed, but in one case, it appears they were being initialized in reverse, resulting in an abort. When I reversed the arguments, the program stopped aborting.

Below is an example of the syntax I'm using. a_ needs to be initialized before b_ in this case. Can you ensure this order of initialization?

class A
{
  public:
    OtherClass a_;
    AnotherClass b_;

    A(OtherClass o, string x, int y)
      : a_(o)
      , b_(a_, x, y) {}
};
Zahn answered 7/8, 2009 at 4:0 Comment(4)
You say you're asking about constructor arguments, but they're evaluated before you ever reach the constructor, and they're evaluated in an unspecified, compiler-determined order. But you're really asking about the order of initialization lists, so I've changed the question title for you.Mastaba
I was asked this question in an interview :)Dagny
The interviewer probably got the question from here :)Zahn
@Zahn No, we didn't.Menell
B
340

It depends on the order of data member declarations in the class. So a_ will be the first one, then b_ will be the second one in your example.

Bouncing answered 7/8, 2009 at 4:4 Comment(4)
In fact, good compilers will warn if you have a different order in the declaration versus the constructor initialiser list. For example, see -Wreorder in gcc.Thumbprint
The reason for which they are constructed in the member declaration order and not in the order in the constructor is that one may have several constructors, but there is only one destructor. And the destructor destroy the members in the reserse order of construction.Hooray
did we mean ...reverse order of declaration. Not of "construction", the destructor cannot possibly see into the constructor to know can it?Humble
@Humble yes, sort of. I think AProgrammer meant "construction" in the sense of actual physical initialization (which as you suggest occurs in the order of declaration), and not in the sense of "order appearing in some constructor's init list". Your wording is clearer.Colfin
K
224

To quote the standard, for clarification:

12.6.2.5

Initialization shall proceed in the following order:

...

  • Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

...

Kassiekassity answered 7/8, 2009 at 4:9 Comment(0)
H
32

The standard reference for this now appears to be 12.6.2 section 13.3:

(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).

Happen answered 17/8, 2016 at 6:59 Comment(0)
L
0

Seeing other answers without to much details into other members initialization I recommend reading more info from standard reference 12.6.2 section 13 (thanks @Adam Getchell for link):

In a non-delegating constructor, initialization proceeds in the following order:

(13.1) — First, and only for the constructor of the most derived class (1.8),
virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.

(13.2) — Then, direct base classes are initialized in declaration order
as they appear in the base-specifier-list
(regardless of the order of the mem-initializers).

(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).

(13.4) — Finally, the compound-statement of the constructor body is executed.

Terminology:

base-specifier-list - list of base classes for derived class. See section 10 of reference.
Example: class A : public virtual B, private C

mem-initializers - list of initializers for members of your class.
Example: A::A() : number(1.0f), text("abc"){ /* ... */}

compound-statement - block of {}, i.e. body of constructor.


That's all, simply said the order:

  1. static variables (see this stackoverflow question C++ static variables initialization order, also that interesting behavior SIOF). In single translation unit order follows declaration order, in different - compilers decide.
  2. virtual base classes as appear by dfs
  3. direct base classes as specified by order in deriving list
  4. non-static variables by declaration (! not initializers order) order
Latria answered 26/7, 2023 at 9:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.