成员初始化

优先初始化器列表,其次默认初始化器,最后默认初始化(对于原始类型就是未初始化)

构造函数体在初始化器列表之后执行

如果没有任何用户声明的构造函数,会生成默认构造函数,它可以被视作是无参数,无初始化器列表,体内为空。但生成的默认构造函数和手动编写的空构造函数仍然有细微区别:

  1. C++20之前explicit默认构造函数不会使得类变成non-aggregate,C++20之后会了
int a;         // no initializer (default initialization)
int b = 5;     // initializer after equals sign (copy initialization)
int c( 6 );    // initializer in parentheses (direct initialization)
 
// List initialization methods (C++11)
int d { 7 };   // initializer in braces (direct list initialization)
int e = { 8 }; // initializer in braces after equals sign (copy list initialization)
int f {};      // initializer is empty braces (value initialization)
 
// Calls Foo() default constructor
Foo f1;           // default initialization
Foo f2{};         // value initialization (preferred)
 
// Calls foo(int) normal constructor
Foo f3 = 3;       // copy initialization (non-explicit constructors only)
Foo f4(4);        // direct initialization
Foo f5{ 5 };      // direct list initialization (preferred)
Foo f6 = { 6 };   // copy list initialization (non-explicit constructors only)
 
// Calls foo(const Foo&) copy constructor
Foo f7 = f3;      // copy initialization
Foo f8(f3);       // direct initialization
Foo f9{ f3 };     // direct list initialization (preferred)
Foo f10 = { f3 }; // copy list initialization

There are three key differences between the initialization forms:

  • List initialization disallows narrowing conversions.
  • Copy initialization only considers non-explicit constructors/conversion functions.
  • List initialization prioritizes matching list constructors over other matching constructors.

copy elision

as-if豁免,故复制构造函数不应当有副作用

Only one user-defined conversion may be applied

printEmployee("Joe"); // we're supplying an string literal argument

其中该函数接受Employee对象,Employee对象只能通过stringview初始化,该代码无法编译通过