成员初始化列表
成员初始化列表是构造函数的一部分,位于构造函数参数列表之后和构造函数体之前。它用于直接初始化类的成员变量。成员初始化列表的语法如下:
ClassName::ConstructorName(参数列表) : 成员变量1(初始值1), 成员变量2(初始值2), ... {
// 构造函数体
}
示例解释
在示例代码中:
class Shallow {
public:
Shallow(int size) : size(size) {
data = new int[size]; // 动态分配内存
for (int i = 0; i < size; ++i) {
data[i] = i;
}
}
// 拷贝构造函数:执行浅拷贝
Shallow(const Shallow& source) : size(source.size), data(source.data) {
std::cout << "Shallow Copy Constructor Called" << std::endl;
}
~Shallow() {
delete[] data; // 释放内存
std::cout << "Destructor Called" << std::endl;
}
void display() const {
for (int i = 0; i < size; ++i) {
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
private:
int* data;
int size;
};
这里的 Shallow(int size) : size(size)
部分做了以下事情:
Shallow(int size)
是构造函数的声明,接受一个int
类型的参数size
。: size(size)
是成员初始化列表,初始化成员变量size
,将构造函数参数size
的值赋给类的成员变量size
。
这等同于在构造函数体中写 this->size = size;
,但成员初始化列表在一些情况下更高效和必要,特别是对于常量成员、引用成员和需要复杂初始化的成员。
为什么使用成员初始化列表
- 效率:对于内置类型和简单对象,成员初始化列表和在构造函数体内赋值差别不大。但对于自定义类类型,成员初始化列表可以避免一次默认构造和一次赋值,直接调用参数化构造函数,提高效率。
- 不可变成员:对于
const
成员或引用成员,必须使用成员初始化列表,因为它们在构造函数体内不能被赋值。 - 初始化顺序:成员初始化列表按照成员声明的顺序进行初始化,而不是在列表中出现的顺序。这可以避免一些顺序依赖的问题。
成员初始化列表的正确使用
确保在成员初始化列表中初始化所有需要的成员,并按照声明顺序书写:
class Example {
public:
Example(int a, int b) : member1(a), member2(b) {
// 构造函数体
}
private:
int member1;
int member2;
};