构造函数的执行可以分成两个阶段,初始化阶段和计算阶段,初始化阶段先于计算阶段。而初始化阶段就是对应着初始化列表那部分,而计算阶段就是构造函数的函数体部分。初始化阶段先于计算阶段执行。
#include<iostream>
class Demon
{
public:
Demon(){}
Demon(int value):value{value}
{
std::cout << "value = " << this->value << std::endl;
this->value = value + 10;
std::cout << "value = " << this->value << std::endl;
}
private:
int value{0};
};
int main()
{
Demon(1);
return 0;
}
构造函数列表初始化比在构造函数函数体内进行赋值效率更高(仅仅针对复杂或比较大的类型的变量,对于基础类型没什么影响)。
假如类成员的基类或成员类都定义了默认构造函数(如存在string类型的类成员),则在初始化时会调用他们的默认构造函数,但如果在构造函数中又对sting成员进行了赋值,则相当于又进行了一次string的拷贝构造。相反,如果放在初始化列表中则只需要调用一次string类的初始化即可;
#include<iostream>
using namespace std;
class Base
{
public:
Base(int i = 10)
{
cout << "Base构造函数:" << i<< endl;
this->i = i;
}
Base(const Base& b)
{
cout << "--Base拷贝构造函数--:" << b.i << endl;
i = b.i;
}
Base& operator=(const Base& b)
{
cout << "--Base赋值构造函数--:" << b.i << endl;
i = b.i;
return *this;
}
int i;
};
class Inher
{
public:
Inher(Base& b) //触发了Base对象的构造函数
{
b1 = b;
b2 = b;
}
Base b1;
Base b2;
};
class Inher2
{
public:
Inher2(Base& b):b1(b), b2(b) //base(b) 会调用拷贝构造函数
{}
Base b1;
Base b2;
};
int main()
{
Base b1(1);
Base b2(2);
std::cout << std::endl;
Inher in(b1);
std::cout << std::endl;
Inher2 in2(b2);
return 0;
}
output:
从上面结果可以看出,在构造函数体内赋值时,会多一次成员的构造过程;