它是一个初始化列表。它允许您直接使用要为其分配的值构造成员变量,而不是默认构造它们,然后在构造函数的主体中分配它们。
假设您有一个A
具有默认构造函数的类和一个接受一个参数的构造函数:
struct A
{
A() : n(0) { } // For scalar types, n = 0 in the constructor's body is equivalent
A(int n) : n(a) { } // Should be marked as "explicit", but not relevant here
int a;
};
和一个X
具有类型成员变量的类A
。的构造函数X
接受一个类型的参数,该参数int
需要分配给A
的变量a
。如果没有初始化列表,你会这样做:
struct X
{
X(int n) { a.a = n; } // First invoke A::A(), then assign n to a.a
A a;
};
但是这里有两条指令而不是一条指令:成员变量的(可能很昂贵)默认构造a
,然后是根据需要更改其状态的赋值。如果您已经知道a
应该构造的参数,那么首先执行默认构造只是为了覆盖该初始化是没有意义的。
但是,必须说,在初始化标量类型时(就像您的示例一样),基于初始化列表的形式等同于基于构造函数主体中的常规赋值的形式,因为标量类型不是零初始化的默认情况下(更准确地说,它们不会以任何方式初始化)。
作为相关信息,在初始化列表中,构造函数参数的名称不会隐藏您要构造的成员变量的名称:
struct X
{
X(int a) : a(a) { } // OK (although I do not like it)
int a;
};
相反,在常规赋值中,a
将被视为赋值两侧的构造函数参数:
struct X
{
X(int a) { a = a; } // Self-assignment of the constructor's argument...
int a;
};
这就是说,我不认为对成员变量和函数参数使用相同的名称是一种好习惯。我之所以提到它,是因为如果您必须阅读其他人编写的代码,那么了解这一点是件好事。