Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it undefined behavior to refer to class members in an initialiser list?

Tags:

c++

Let's say I have the following:

class A {
   B member1;
   C member2;
public:
   A();
};

class B {
public:
   C& ref_to_c;
   B( C& ref_to_c );
};

class C {
 ...
};

B requires that a reference to C be provided on its constructor. If class A provides C, is it legal to specify A's initialiser list as the following...

A() : member1( B( member2 ) ) {}

That is to say, does member2 exist in the initialiser list phase, or is this undefined behaviour?

like image 810
Mike Nielsen Avatar asked Dec 24 '16 20:12

Mike Nielsen


People also ask

What is an initializer list used for?

Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.

What is a member initializer list?

Member initializer list is the place where non-default initialization of these objects can be specified. For bases and non-static data members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.

How do you initialize a class member in C++?

There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.

How do you initialize a constant data member in a class in C++?

To initialize the const value using constructor, we have to use the initialize list. This initializer list is used to initialize the data member of a class. The list of members, that will be initialized, will be present after the constructor after colon. members will be separated using comma.


2 Answers

Intialization is as follows:

5 Initialization shall proceed in the following order:

— First, and only for the constructor of the most derived class as described below, virtual base classes shall be 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 class names in the derived class base-specifier-list.

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

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

— Finally, the body of the constructor is executed. [Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. ]


Which basically means that member1 will always be initialized before member2. So, B's constructor will run first. Even if you'd call them in reverse order explictly in A's constructor:

A() : member2(foo), member1(bar) {}

it doesn't make a difference. Now, referencing an uninitialized object is not UB by itself but it can be depending on B's constructor. You should switch the order of declaration:

C member2;
B member1;
like image 113
Hatted Rooster Avatar answered Oct 16 '22 21:10

Hatted Rooster


You are making up member1 that contains a reference to memebr2. That is not constructed yet, but the compiler already knows where it will be (so it can provide a reference).

It will work, but will be UB if you try -for example in B ctor- to access the ref_to_c value in some kind of expression, since the reference is actually aliasing an uninitialized memory, that will be initialized during member2 construction, that would happen later.

The same problem will be in B destructor, where member2 will be destroyed before ref_to_c.

It will be better if you swap member2 and member1 in A, so that you will initialize the reference with a constructed object, making every possible usage, defined.

like image 4
Emilio Garavaglia Avatar answered Oct 16 '22 20:10

Emilio Garavaglia