Execution of constructor is done in two phases:
The initialization phase
Body execution phase which consists of all the statements within the body of constructor. Note that data members of class type are always initialized in the initialization phase, regardless of whether the member is initialized explicitly in the constructor initializer list. Initialization happens before any the statement execution of the constructor body.
Let us consider a way of initializing an instance of class student by the constructor -
Student(string &fn, string &ln, int i, int y = Freshman)
: first_name(fn)
, last_name(ln)
, id(i)
, year(y)
{}
This is another , but 'inefficient' and 'inelegant' way of doing the same -
Student(string &fn, string &ln, int i, int y = Freshman)
{
first_name = fn;
last_name = ln;
id = i;
year = y;
}
This constructor in the new code (above code) assigns the members of class Student. It does not explicitly initialize them. Whether there is an explicit initializer or not, the first_name and last_name members are initialized even before the constructor is executed. This constructor implicitly uses the default string constructor to initialize the first_name and last_name members. When the body of the constructor is executed, the first_name and last_name members already have values. Those values are overwritten by the assignment inside the constructor body.
So ,this means by the time the execution reaches the opening bracket of the constructor , this is the condition -
- 'first_name', which is a string is initialized by calling the default string constructor ( the one which compiler 'makes') .
- 'last_name', which is a string开发者_运维百科 is initialized by calling the default string constructor ( the one which compiler 'makes') .
- 'id', which is an integer is uninitialized .
- 'year', which is an integer is uninitialized .
And now ,it's clear , the assignments are done to each of the four variables , in the body of the constructor .
Is my understanding of this thing right ? I somehow feel I am missing something .
Also , while using the initialization lists , are the default constructors (one which compiler makes for us) , called and passed with our parameters (in case of string) and initialization done as in " int id = i ; " in case of id(i) ??
PS : Most of the quotes are from this link -
http://www.bogotobogo.com/cplusplus/constructor.php
Your understanding is mostly correct, except that you must initialize const
members in the initialiser because you can't assign to them (because they're const
) in the body of the constructor or anywhere else ever again. If you try to leave a const
member uninitialised, you'll get a compile error.
And yes, in initialisation lists, the constructor of the object that matches the arguments you give it is called. If there are no arguments(e.g. : blah()
) then the default constructor is called.
Aditionally, there are some instances where you absolutely must use an initialiser list (it is not optional), such as
- When the class has
const
members - When the class is an immediate child of a class without a default constructor
- When the class has reference members
You're not saying how your Student
class is defined, but you may be confused about one thing: In your second, "inelegant" version, first_name
is not necessarily a const string -- rather, fn
is a reference to a const string, and you assign the value of that to your member variable first_name
.
Now, on to initializer lists: The entire point of those is that you get to specify which constructors of the member objects are called. Without the list, all member objects have their default constructors called (or more accurately, they are default-initialized). However, any object that you mention in the initializer list will have that constructor (or rather "initializer") called instead.
The initializer list isn't just mere decoration. It is essential, because member objects and subobjects may not even be default-constructible, and so an initializer must be provided. The const member is actually a very good example:
struct Foo
{
const int n;
Foo(); // error! What is n?
Foo(int m) : n(m) { } // OK
};
Here's another example, this time deriving from a base class that has no default constructor:
struct Bar : Foo
{
Bar(); // error! How to initialize Foo?
Bar() : Foo(5) { } // OK, now Bar::n == 5
};
Also , while using the initialization lists , are the default constructors (one which compiler makes for us) , called and passed with our parameters (in case of string) and initialization done as in " int id = i ; " in case of id(i) ??
First, default constructors are not necessarily "one which compiler makes for us". They are simply constructors with no parameters, e.g. Student()
. Sometimes the compiler automatically generates one, like for int
, and sometimes it has to be written, like the one for std::string
.
The easy way to think about it is this: If an initializer is present, then the corresponding constructor is called. So, assuming first_name
is std::string
, then the initializer first_name(fn)
results first_name
getting constructed with std::string::string(const std::string&)
, passing fn
as the parameter. If an initializer is not used, then first_name
is constructed with std::string::string()
before the { ... }
code executes, then when you write first_name = fn;
, that results in a call to std::string::operator =(const std::string&)
, passing fn
as the parameter.
Finally, the important thing to realize about initializers is that they execute in the order that members are declared in the class, not in the order you write them in the constructor. Also, initializers for base class constructors happen before member initialization.
精彩评论