C++类构造函数初始化列表
构造函数的初始化列表以一个冒号可是,接着是一个以逗号分割的数据成员列表,每个数据成员跟一个放在圆括号中的初始化式。
构造函数可以定义在类的内部或外部,但是构造函数的初始化式只在构造函数的定义中而不是在声明中指定。
class CExample {
public:
int a;
float b;
//构造函数初始化列表
CExample(): a(0),b(8.8)
{}
//构造函数内部赋值
CExample()
{
a=0;
b=8.8;
}
};
上面的例子中两个构造函数的结果是一样的。上面的构造函数 (使用初始化列表的构造函数)显式的初始化类的成员 ;而没使用初始化列表的构造函数是对类的成员赋值,并没有进行显式的初始化。
初始化和赋值对内置类型的成员没有什么大的区别,像上面的任一个构造函数都可以。 对非内置类型成员变量,为了避免两次构造,推荐使用类构造函数初始化列表。 但有的时候 必须用带有初始化列表的构造函数 :
1. 成员类型是没有默认构造函数的类。 若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。
2. const成员 或 引用类型 的成员。因为const对象或引用类型只能初始化,不能对他们赋值。 对于简单数据成员,使用成员初始化列表和在函数体中使用赋值没有什么区别。然而,对于本身就是类对象的成员来说,使用成员初始化列表的效率更高。
对于const数据成员,必须在执行到构造函数体之前,即创建对象时进行初始化。C++提供了一种特殊的语法来完成初始化,它叫做成员初始化列表。成员初始化列表由逗号分隔的初始化列表组成(前面带冒号)。它位于参数列表的右括号之后、函数体左括号之前。
通常,初值可以是常量或构造函数的参数列表中的参数。这种方法并不限于初始化常量,可以是其他的数据成员。但是,只有构造函数可以使用这种初始化列表。
成员初始化列表的语法:
如果Classy是一个类,而mem1、mem2和mem3都是这个类的数据成员,则类构造函数可以使用如下的语法来初始化数据成员:
Classy::Classy(int n,int m):mem1(n),mem2(0),mem3(n*m+2)
{
//.....
}
上述代码将mem1初始化n,将mem2初始化为0,将mem3初始化为n*m+2.从概念上说,这些初始化构造是在对象创建时完成的,此时还未执行括号中的任何代码。请注意一下几点:
1)这种格式只能用于构造函数
2)必须用这种格式来初始化非静态const数据成员(至少在C++11之前是这样的);
3)必须使用这个格式来初始化引用数据成员。
数据成员被初始化的顺序与他们出现在类声明中的顺序相同,与初始化器中的排列顺序无关。
警告:不能将成员初始化列表语法用于构造函数之外的其他类方法。
C++11的类内初始化
C++11允许以更直观的方式进行初始化:
class Classy
{
int mem1=10;
const int mem2=20;
};
这与在构造函数中使用成员初始化列表等价:
Classy::Classy():mem1(10),mem2(20){...}
成员mem1和mem2将分别被初始化为10和20,除非调用了使用成员初始化列表的构造函数。在这种情况下,实际列表将覆盖这些默认初始化:
Classy::Classy(int n):mem1(n){}
在这里,构造函数将使用n来初始化mem1,但mem2仍被设置为20.