C ++:如何通过初始化列表进行构造?
C++: how is construction by initialization list done?
C++ 允许实例化 class,通过初始化列表设置 public 成员的值,如下例所示 b1
:
class B {
public:
int i;
std::string str;
};
B b1{ 42,"foo" };
B b2();
;但是,如果我提供构造函数
B(int k) { }
,它不会编译。
那么,幕后发生了什么?
是不是当没有提供构造函数时,编译器会提供一个?但是它怎么能提供一个初始化列表呢?我认为它只会提供一个不接受任何输入的 "blank" 构造函数,如 b2
的示例所示。还是两者都提供?
But how could it provide one with initialization list?
不,不会。
注意执行list initialization B b1{ 42,"foo" };
, aggregate initialization。
If T
is an aggregate type, aggregate initialization is performed.
而B
是一个aggregate type,
An aggregate is one of the following types:
array type
class type (typically, struct or union), that has
no private or protected non-static data members
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
no virtual, private, or protected base classes
no virtual member functions
这就是 B b1{ 42,"foo" };
运作良好的原因。
并且如果你提供了一个用户定义的构造函数,B
变成了非聚合类型,那么聚合初始化将不再起作用。在这种情况下,您只能像 B b1{42};
或 B b2(42);
一样初始化 B
,这将调用适当的构造函数。
顺便说一句:在提供了一个用户定义的构造函数(带一个参数)之后,implicitly-declared default constructor 将不会被编译器再次声明。这意味着 B b2;
或 B b2{};
将不再有效。
BTW2:B b2();
可能是一个函数声明。参见 Most vexing parse。
C++ 允许实例化 class,通过初始化列表设置 public 成员的值,如下例所示 b1
:
class B {
public:
int i;
std::string str;
};
B b1{ 42,"foo" };
B b2();
;但是,如果我提供构造函数
B(int k) { }
,它不会编译。
那么,幕后发生了什么?
是不是当没有提供构造函数时,编译器会提供一个?但是它怎么能提供一个初始化列表呢?我认为它只会提供一个不接受任何输入的 "blank" 构造函数,如 b2
的示例所示。还是两者都提供?
But how could it provide one with initialization list?
不,不会。
注意执行list initialization B b1{ 42,"foo" };
, aggregate initialization。
If
T
is an aggregate type, aggregate initialization is performed.
而B
是一个aggregate type,
An aggregate is one of the following types:
array type class type (typically, struct or union), that has no private or protected non-static data members no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed) no virtual, private, or protected base classes no virtual member functions
这就是 B b1{ 42,"foo" };
运作良好的原因。
并且如果你提供了一个用户定义的构造函数,B
变成了非聚合类型,那么聚合初始化将不再起作用。在这种情况下,您只能像 B b1{42};
或 B b2(42);
一样初始化 B
,这将调用适当的构造函数。
顺便说一句:在提供了一个用户定义的构造函数(带一个参数)之后,implicitly-declared default constructor 将不会被编译器再次声明。这意味着 B b2;
或 B b2{};
将不再有效。
BTW2:B b2();
可能是一个函数声明。参见 Most vexing parse。