一、什么是 C++ 中的初始化列表?它的作用是什么?
作用:c++提供了初始化列表语法,用来初始化属性
语法:构造函数():属性1(值1),属性2(值2)...{ }
- 构造函数是给成员变量(属性)赋值,初始化参数列表是给成员变量(属性)初始化的。
- 它只能在构造函数里使用,可以给所有成员设置初始化参数。
- 并且成员的初始化顺序和在初始化参数列表中的顺序无关,与在类中声明顺序有关
class B
{
public:int a;int b;B(int num1) : b(num1),a(b){cout << "B的构造";}
};
int main() {B hh(2);cout << hh.a << " " << hh.b;return 0;
}
//输出:B的构造-858993460 2
//看似先初始化 b,实际先初始化 a, 所以a(b)此时b还不存在导致 a 的值不是 2
- const 类型和引用类型在初始化参数列表中初始化。
- 初始化参数列表可以调用对象成员的构造函数(这个对象成员的类没有默认构造函数就需要采用这种初始化参数列表的形式调用有参构造)
// 调用对象成员的构造
class A {
public:A(int num){cout << "A的构造" << endl;}
};class B
{A a; // 对象成员
public:B(int num) :a(num)// 此时创建 a 需要有参构造{cout << "B的构造";}
};
int main() {B b(2);return 0;
}
- 当父类没有默认的构造函数时,可以使用初始化参数列表调用父类的有参构造创建父类对象
// 调用父类的构造
class A {
public:A(int num){cout << "A的构造" << endl;}
};class B : public A
{int a;
public:B(int num) :A(num)// 此时父类没有默认构造,创建子类对象必须先创建父类对象才能有父类中的成员变量{cout << "B的构造";}
};
int main() {B b(2);return 0;
}
二、初始化列表和在构造函数体内赋值有什么区别?
- 使用初始化列表进行成员初始化效率更高。对于自定义类型(如类对象),初始化列表直接调用成员对象的构造函数进行初始化。在构造函数体中进行赋值操作,实际上是先进行默认初始化(对于类类型成员,调用默认构造函数),然后再进行赋值操作。
- 对于 const 成员和引用成员,必须使用初始化列表进行初始化。因为 const 成员一旦初始化就不能再赋值,引用必须在定义的时候初始化。
- 成员的初始化顺序是由成员在类中的声明顺序决定的,而不是初始化列表中的顺序。这提供了一种固定的初始化顺序规则。构造函数体内赋值则是按照代码编写的顺序进行赋值,不受成员声明顺序的限制。
- 初始化列表紧跟在构造函数的参数列表之后,以冒号
:
开头,后面是成员变量及其初始化值,多个成员变量之间用逗号分隔。在构造函数体内部,使用赋值语句(如member = value;
)来给成员变量赋值,这和普通的变量赋值语句语法相同。