初始化列表
内容简介
初始化列表用于在构造函数体执行前初始化成员。它不是简单的语法糖,很多成员必须通过初始化列表初始化。
用法
class Person {
public:
Person(int a, int b, int c)
: a_(a), b_(b), c_(c)
{
}
private:
int a_;
int b_;
int c_;
};为什么不用构造函数体内赋值
构造函数体内写法:
Person::Person(int a, int b, int c)
{
a_ = a;
b_ = b;
c_ = c;
}这不是初始化,而是先默认初始化成员,再赋值。对于简单 int 差异不明显,但对于 const、引用、无默认构造的成员对象,必须用初始化列表。
必须用初始化列表的场景
const 成员
class Config {
public:
explicit Config(int port) : port_(port) {}
private:
const int port_;
};引用成员
class Holder {
public:
explicit Holder(int& value) : value_(value) {}
private:
int& value_;
};成员对象没有默认构造函数
class Phone {
public:
explicit Phone(std::string name) : name_(std::move(name)) {}
private:
std::string name_;
};
class Person {
public:
Person(std::string name, std::string phone)
: name_(std::move(name)), phone_(std::move(phone))
{
}
private:
std::string name_;
Phone phone_;
};初始化顺序
成员初始化顺序由成员在类中的声明顺序决定,不由初始化列表书写顺序决定。
class Demo {
public:
Demo() : b_(1), a_(b_) {}
private:
int a_;
int b_;
};这里 a_ 会先初始化,因为它先声明。不要依赖初始化列表顺序制造隐式关系。
最佳代码实践
- 构造函数优先使用初始化列表。
- 初始化列表顺序和成员声明顺序保持一致。
- 构造函数参数和成员同名时,可用结尾下划线区分成员变量。
- 成员对象初始化失败时,已构造完成的成员会自动析构。
错误用法
Person::Person() : a_(1), b_(2), c_(3);问题:这是声明,不是构造函数定义。构造函数需要函数体:
Person::Person() : a_(1), b_(2), c_(3)
{
}注意事项
- 初始化列表是 C++ 对象生命周期的重要组成部分。
- 它和 cpp类对象作为成员、cpp构造函数调用规则 强相关。
学习路径
- 上一节:cpp深拷贝和浅拷贝
- 当前阶段:cppOOP
- 下一节:cpp类对象作为成员