当使用成员初始化列表时,类类型成员放在初始化列表里,可明显提高效率。
初始化列表中的代码,可以看做是被编译器安插到构造函数体内的这些代码实在任何用户自己的构造函数体代码之前被执行的,要区分用户代码和编译器插进来的代码。
给出示例代码
class X {
public:
int m_i;
X(int value = 0) :m_i(value)
{
printf("this = %p", this);
cout << "X(int)构造函数被调用" << endl;
}
X(const X &tmpv)
{
printf("this = %p", this);
cout << "X拷贝构造函数被调用" << endl;
}
X& operator=(const X &tmpv)
{
printf("this = %p", this);
cout << "X拷贝赋值运算符被调用" << endl;
return *this;
}
~X()
{
printf("this = %p", this);
cout << "X析构函数被调用" << endl;
}
};
class Y{
public:
X xobj;//类类型对象
Y(int tmpvalue) :xobj(1000)//这里构造了xobj,此处若没有使用初始化成员列表,耗费了一次构造函数调用的机会
// 编译器角度(没用初始化列表)
//X xobj;
//xobj.X::X();
// 编译器角度(用了初始化列表)
//X xobj;
//xobj.X::X(1000);
{
//xobj = 1000;//若不使用初始化列表。这里构造一个临时对象,把临时对象内容给了xobj,之后释放xobj
//编译器视角
//x tmpobj;// (1)生成临时对象
//tmpobj.X::X(1000);// (2)临时对象调用构造函数
//xobj.X::operator=(tmpobj);// (3)调用拷贝赋值运算符
//tmpobj.X::~X(); // (4)调用析构函数
}
};
调用构造函数时,对象在程序进入构造函数函数体之前被创建。也就是说,调用构造函数的时候,先创建对象,再进入函数体。若不使用初始化成员列表会浪费一次赋值机会,进入函数体后另外赋值。