views:

188

answers:

7

I have a global member data object, defined in a header (for class MyMainObj) like this.

class MyMainObj
{
    MyDataObj obj;
}

MyDataObj has a default constructor. When is the constructor for MyDataObj called? Is it called as part of the creation of MyMainObj?

A: 

Yes, the constructor would be called whenever a MyMainObj instance is created.

I'm a bit confused by the "global member" terminology - the way you've declared that object it would be a local variable inside the constructor. Am I missing something here?

Eric Petroelje
More accurately, it would be called whenever a MyMainObject instance is *default* constructed (because this is the default ctor). It wouldn't be in the case of another constructor, since it's local to this one (though, of course, any other ctors could create such an object as well...
Jerry Coffin
+3  A: 

With that code, obj isn't a member of MyMainObj -- it's simply a local object inside that constructor. As such, it'll only be constructed when/if that constructor is invoked.

Jerry Coffin
oops, ok i fixed it.
Krakkos
+2  A: 

MyDataObj in this case is not a member of MyMainObj, it's a local variable.

But, constructors for data members are called in your class's constructor. The default constructor for every member is called before execution reaches the first line in the constructor, unless you explicitly specify a constructor using an initializer list, in which case that constructor is called instead.

rlbond
The part about "explicitly specify a constructor using an initializer list" is not clear. Do you imply that member constructors won't be called in that case, or that they will be called at a different time, or something else?
Pavel Minaev
I thought it was obvious, but by explicitly specifying a constructor in the initializer list, that constructor is used instead of the default.
rlbond
A: 

Given a class A:

class A {
    MyDataObj obj;
}

If you don't write the constructor for A, the compiler will create one for you, which will create obj as part of constructing A (and destroy obj as part of destroying A.

If you do write a constructor for A, then obj will be created before your constructor runs, although you can reassign it:

class A {
    MyDataObj obj;
  public:
    A() { } // obj created, but the value may or may not be predictable
}

class AA {
    MyDataObj obj;
  public:
    AA()
    {
        obj = MyDataObj(5);
    }
}

class AAA {
    MyDataObj obj;
  public:
    AAA() : obj(5) { } // member initializer list, my preferred method
}

With the third option, the data objects are created before the member initializer list runs, and the values are assigned in the order they are declared in AAA, NOT the order they are listed in the member initializer list.

UPDATE: There is a difference between creation and initialization. Space for the data members (and the base classes, and the data members for the base classes) is always set aside -- which I would call "creation." However, that doesn't mean a useful value is stored in that memory. There are separate rules for whether an object is default initialized, which depend on the type of the data member (primitive, POD, non-POD) and, IIRC, the storage class of the main object (local, static, global). The easiest way to avoid surprises in this area is to simply make sure you explicitly initialize everything.

Max Lybbert
Actually A:obj, the obj IS created with it's default constructor.
Alexander Pogrebnyak
Exactly. Your first variant claims that the data member is "never created", which is incorrect. If a data member is not mentioned in the constructor initializer list, it is implictly initialized with its own default constructor (if it has any).
AndreyT
It's more complicated than that. Members (and base classes) _of non-POD types_ not listed in ctor initialization list are default-initialized, which indeed means default ctor. But any member or base PODs aren't initialized at all.
Pavel Minaev
@Andrey: Thanks, I had missed that comment when I edited the question for an earlier correction. @Pavel: Thanks for the clarification; I knew default initialization happened in some cases, but I couldn't remember when it didn't happen.
Max Lybbert
+3  A: 

Concerning your code, you have a function with a variable inside. Upon entering the function, you will run to the line of code that declares the variable, and the constructor will be run then.

But you say "creation of MyMainObj". It's a function, it can only be called, not created.


This is all concerning the title question, "when are members constructed?" This would apply if MyMainObj was a class and not a function.

Your member objects are constructed in the order of which they appear in the class declaration. All objects are full constructed upon entering the constructor. (But this does not include the class itself!)

That is to say, by the time the class enters its constructor, all the members have finished their constructor.

Objects are destructed in reverse order, in the destructor (after the destructor is run).

In a pseudo-diagram:

MyClass
    Member1
    Member2
    Member3

Construction:
    Member1
    Member2
    Member3
    MyClass

Destruction:
    MyClass
    Member3
    Member2
    Member1

You can manually call the members constructor using an initialization list:

class foo
{
public:
    foo(void) : i(0) // construct i with 0.
    {
    }

    int i;
};

There are various question on SO about initialization lists. Initialization list order, Copy-construction initialization list, and more.

GMan
It's worth noting that member subobjects are _always_ constructed in the order in which they are declared in the class, _regardless_ of the order in which the corresponding member initializers are listed - forgetting about that is a frequent source of subtle bugs.
Pavel Minaev
Indeed, most compilers will warn about this too.
GMan
A: 

Yes, as other stated the member will be created on the owner class creation, on construction (be it generated by the compiler or with a provided constructor).

The order of creation will be the same as how your members apear in the class declaration. For example :

class MyType
{
    Thing a;
    Thing b;
    Thing d;
    Thing c;
 };

Whatever constructor is used, whatever the order in a initialization list, the members will be constructed in this order : a, b, d, c. Once it's all done, the constructor code will be executed (if it exists) and only then your whole object will be constructed.

Klaim
A: 

Upon entering an object constructor, memory has already been allocated for it. Then the execution order is as follows:

  1. Base class constructor, if any, as specified in the initialisation list; if not specified, the default constructor is used.

  2. The constructors for the member data, as specified in the initalisation list (default if not specified), in the order they are declared in the class definition. The order in which they are specified in the initialisation list is irrelevant.

  3. The constructor body.

In the example set in the question, the first thing that would be executed upon entering the default constructor of MyMainObj would be the default constructor of MyDataObj to construct the member data obj.

Gorpik