1

Suppose I have a class Alpha, which has two member variables, beta and gamma, which are objects of classes Beta and Gamma respectively:

class Alpha
{
public:
    Beta beta_;
    Gamma gamma_;
};

Now, the class Gamma itself has a member variable p_beta, which is a pointer to that same beta variable in Alpha. However, Gamma does not have a default constructor, but instead it must be constructed by passing p_beta:

class Gamma
{
public:
    Beta* p_beta_;
    Gamma(Beta* p_beta)
    {
        p_beta_ = p_beta;
    }
};

So then, if I want to create an object alpha of class Alpha, I need to construct its member gamma_ in the initializer list of Alpha, given that Gamma does not have a default constructor:

class Alpha
{
public:
    Beta beta_;
    Gamma gamma_;
    Alpha() : gamma_(&beta_){}
};

My question is: Will beta_ have already been created by the time gamma_ is constructed in this initializer list? I would have thought that the initializer list is called before creating any of the other member variables, in which case beta_ will not exist. If beta_ has not been created by then, then how can I pass a pointer to beta_ when constructing gamma_?

Karnivaurus
  • 22,823
  • 57
  • 147
  • 247

3 Answers3

3

The non-static non-variant data members of a class are initialized in declaration order, without exception. The fact that you haven't specified a mem-initializer for beta_ simply means that it will be default-initialized, and this default initialization takes place before the initialization of gamma_ because beta_ precedes gamma_ in declaration order.

Besides that, even if you changed the order of beta_ and gamma_ in the class definition, there's nothing wrong with passing around a pointer to an object that hasn't been initialized yet.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 1
    _there's nothing wrong with passing around a pointer to an object that hasn't been initialized yet_: But beware! receivers of this pointer may want to use it, not just to store it for later, And then you will have UB. – rodrigo May 08 '15 at 19:30
2

Will beta_ have already been created by the time gamma_ is constructed in this initializer list?

Yes, beta_ will have been default-constructed before gamma_, so it is safe to use its address. Initialization of non-static data members occurs in declaration order, and destruction in reverse-declaration order.

David G
  • 94,763
  • 41
  • 167
  • 253
0

From [class.base.init]/13, emphasis mine:

In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class (1.8), virtual base classes are...
— Then, direct base classes are initialized in declaration order ...
— 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).

So yes, beta_ will have been constructed before gamma_ (the order of the initializers is irrelevant)

Barry
  • 286,269
  • 29
  • 621
  • 977