C++类_初始化列表
在 C++ 里,初始化列表是构造函数特有的一种语法,它能够在对象创建时初始化成员变量。以下会详细介绍初始化列表的语法、使用场景以及注意事项。
语法
初始化列表置于构造函数的参数列表之后、函数体之前,用冒号分隔,成员变量的初始化以逗号分隔。示例如下:
#include <iostream>
class MyClass {
private:int num;double d;
public:// 构造函数使用初始化列表MyClass(int n, double val) : num(n), d(val) {// 构造函数体}void printValues() {std::cout << "num: " << num << ", d: " << d << std::endl;}
};int main() {MyClass obj(10, 3.14);obj.printValues();return 0;
}
在上述代码中,MyClass
的构造函数使用了初始化列表来初始化num
和d
两个成员变量。
使用场景
1. 常量成员变量初始化
常量成员变量一旦初始化就不能再赋值,所以必须在初始化列表中进行初始化。
#include <iostream>
class MyClass {
private:const int num;
public:// 初始化常量成员变量MyClass(int n) : num(n) {}int getNum() const {return num;}
};int main() {MyClass obj(10);std::cout << "num: " << obj.getNum() << std::endl;return 0;
}
2. 引用成员变量初始化
引用必须在定义时初始化,因此也需要在初始化列表中完成。
#include <iostream>
class MyClass {
private:int& ref;
public:// 初始化引用成员变量MyClass(int& value) : ref(value) {}int getRefValue() const {return ref;}
};int main() {int x = 10;MyClass obj(x);std::cout << "ref value: " << obj.getRefValue() << std::endl;return 0;
}
3. 基类构造函数调用
在派生类的构造函数中,可利用初始化列表调用基类的构造函数。
#include <iostream>
class Base {
private:int num;
public:Base(int n) : num(n) {std::cout << "Base constructor called with num: " << num << std::endl;}
};class Derived : public Base {
public:// 调用基类构造函数Derived(int n) : Base(n) {std::cout << "Derived constructor called" << std::endl;}
};int main() {Derived obj(10);return 0;
}
注意事项
1. 初始化顺序
成员变量的初始化顺序由它们在类中声明的顺序决定,而非在初始化列表中的顺序。
#include <iostream>
class MyClass {
private:int a;int b;
public:// 初始化列表顺序与声明顺序不一致MyClass(int x) : b(x), a(b) {std::cout << "a: " << a << ", b: " << b << std::endl;}
};int main() {MyClass obj(10);return 0;
}
在上述代码中,虽然初始化列表里b
先于a
初始化,但实际是a
先初始化,此时b
尚未初始化,所以a
的值是未定义的。
2. 异常处理
若初始化列表中某个成员变量初始化失败,构造函数可能抛出异常,对象创建会失败。所以在初始化列表中使用可能抛出异常的代码时要格外小心。
3. 性能考量
使用初始化列表通常比在构造函数体中赋值更高效,因为初始化列表是在对象创建时直接初始化成员变量,而在构造函数体中赋值是先默认初始化成员变量,再进行赋值操作。