When are member data constructors called?
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 cons开发者_如何学JAVAtructor for MyDataObj
called?
Is it called as part of the creation of MyMainObj
?
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.
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.
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.
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?
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.
Upon entering an object constructor, memory has already been allocated for it. Then the execution order is as follows:
Base class constructor, if any, as specified in the initialisation list; if not specified, the default constructor is used.
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.
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.
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.
精彩评论