C++ 支持显式初始化的两种形式。
提供包含在括号内的初始值设定项列表:
String sFileName( "FILE.DAT" );
带括号的列表中的项被视为类构造函数的参数。 利用此形式的初始化,可启用对带多个值的对象的初始化,并且可将其与 new 运算符结合使用。 例如:
Rect *pRect = new Rect( 10, 15, 24, 97 );
使用等号初始化语法提供单一初始值设定项。 例如:
String sFileName = "FILE.DAT";
虽然上面的示例的工作方式与为第一个列表项中的 String 显示的示例的工作方式相同,但该语法不适合用于在可用存储内分配的对象。
等号右侧的单个表达式将用作类的复制构造函数的参数;因此,它必须是一个可转换为类类型的类型。
请注意,由于初始化上下文中的等号 (=) 与赋值运算符不同,因此重载 operator= 对初始化不起作用。
等号初始化语法与函数样式语法不同,即使大多数情况下生成的代码都相同。 差异在于,在使用等号语法时,编译器的行为必须像发生以下事件序列时的行为一样:
创建一个与要初始化的对象的类型相同的临时对象。
将该临时对象复制到对象。
构造函数先必须是可访问的,然后编译器才能执行这些步骤。 即使编译器可以在大多数情况下消除临时创建和复制步骤,不可访问的复制构造函数也会导致等号初始化失败(在 /Za、/Ze(禁用语言扩展)下)。 请看下面的示例:
// spec1_explicit_initialization.cpp
// compile with: /Za
class anInt {
anInt( const anInt © ) {} // private copy constructor
public:
anInt( int ) {} // public constructor
};
int main() {
// Access-control violation.
// Attempt to reference private copy constructor.
anInt myInt = 7; // C2248
anInt myInt2(7); // Correct; no copy constructor called.
}
当调用函数时,将使用该形式从概念上初始化通过值传递的类类型参数和通过值返回的对象:
type-name name = value
例如:
String s = "C++";
因此,它遵循参数类型必须是可转换为将作为参数传递的类类型的类型。 类的复制构造函数以及接受实参类型的用户定义的转换运算符或构造函数必须是公共的。
在使用 new 运算符的表达式中,使用该形式从概念上初始化在可用存储中分配的对象:
type-name name**(** initializer1, initializer2, ... initializern )
例如:
String *ps = new String( "C++" );
也将通过此方式从概念上初始化类的基类组件和成员对象的初始值设定项。(有关详细信息,请参阅初始化基和成员。)