1 为什么要完成初始化
读取未初始化的值会导致不明确的行为,最终导致不可测知的程序行为。
所以,永远在使用对象之前进行初始化
2 内置类型的初始化
内置类型,必须手工初始化
3 自定义类型初始化-- 构造函数
确保每一个构造函数都将对象的每一个成员初始化
- 不要混淆赋值和初始化
class Address
{
public:
Address(){ std::cout << "Address::Address()" << std::endl; }
Address(const Address& another){ std::cout << "Address::Address(const Address& another)" << std::endl; }
const Address operator=(const Address& another) { std::cout << "const Address Address::operator=(const Address& another)" << std::endl; }
};
class ABEntry
{
public:
ABEntry(const std::string& name, const Address& address, int number);
private:
std::string theName;
Address theAddress;
int numTimesConsulted;
};
ABEntry::ABEntry(const std::string& name, const Address& address)
{
theName = name; //这些都是赋值,不是初始化
theAddress = address;
numTimesConsulted = 0;
}
int main()
{
Address add;
ABEntry entry("Scott Mayers", add);
return 0;
}
运行结果:
上述情况发生了两次构造,一次赋值,不是最佳做法
C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前
最佳做法:成员初始化列表替换赋值动作
4 初始化列表 为什么高效
ABEntry::ABEntry(const std::string& name, const Address& address)
:theName(name), theAddress(address), numTimesConsulted(0)
{
}
运行结果:
上述情况发生了一次构造,一次拷贝构造,因此效率提高
注意:对于内置类型,其初始化和赋值的成本相同,为了保持一致性,避免遗漏,也请一定用初始化列表处理
5 初始化列表 顺序问题
class成员变量总是以其声明次序被初始化,与在初始化列表中的顺序无关
为避免某些可能存在的晦涩错误,最好总是以其声明次序安排初始化列表顺序