Will the initialization list always be processed before the constructor code?
In other words, will the following code always print <unknown>, and the constructed class will have ‘known’ as value for source_ (if the global variable something is true)?
class Foo { std::string source_; public: Foo() : source_('<unknown>') { std::cout << source_ << std::endl; if(something){ source_ = 'known'; } } };
Yes, it will, as per
C++11: 12.6.2 /10(same section inC++14,15.6.2 /13inC++17):In a non-delegating constructor, initialization proceeds in the following order (my bold):
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.
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).
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).
Finally, the compound-statement of the constructor body is executed.
The main reason for using init-lists is to help the compiler with optimisation. Init-lists for non-basic types (i.e., class objects rather than
int,float, etc.) can generally be constructed in-place.If you create the object then assign to it in the constructor, this generally results in the creation and destruction of temporary objects, which is inefficient.
Init-lists can avoid this (if the compiler is up to it, of course but most of them should be).
The following complete program will output 7 but this is for a specific compiler (CygWin g++) so it doesn’t guarantee that behaviour any more than the sample in the original question.
However, as per the citation in the first paragraph above, the standard does actually guarantee it.