• ( expression-list ):优先调用非聚合初始化,且会存在隐式转换
  • = expression
  • { initializer-list }:如果有聚合初始化(initializer_list<>),就调用聚合初始化,没有的话就调用符合条件的非聚合初始化
  • = { initializer-list }:同上
  • 使用 auto 声明的变量括号初始化,只允许一个参数的情况
  • {}() 调用构造函数初始化的方式,不同点在于 {} 没有类型的隐式转换,比如 int x(1.2); 和 int x = 1.2; 通过隐式的对浮点值进行向下取整,然后将其转换为整型,从而将 x 的值初始化为 1。相反的, int x{1.2}; 将会遇到编译错误,初始化列表中的初始值,需要与变量声明的类型完全匹配。

测试代码一:

// #define AGGREGATE_INIT
class Test{
public:
    Test(int a, float b, char* c){
        cout << "int float char* initialize..." << endl;
    }
    Test(int a, int b, int c){
        cout << "int int int initialize..." << endl;
    }
    Test(int a, double b, float c){
        cout << "int double float initialize..." << endl;
    }
#ifdef AGGREGATE_INIT
    Test(initializer_list<int> ls){
        cout << "initializer_list initialize..." << endl;
    }
#endif
};
int main()
{
    char cc[] = "abc";
    Test t1{10, 1.2, cc};       // int float char* initialize...
    
    Test t2{1, 2, 3};           // initializer_list initialize...
    t2 = {4, 5, 6};             // initializer_list initialize...
    // 如果存在聚合初始化构造会报错,此时只会匹配聚合初始化
    // t2 = {4, 4.4, 4.f};      // error: narrowing conversion of ‘4.4000000000000004e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
    // Test t3{4, 4.4, 4.f};    // error: narrowing conversion of ‘4.4000000000000004e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
    // 如果不存在聚合初始化,会找匹配的非聚合初始化
    t2 = {4, 4.4, 4.f};         // int double float initialize...
    Test t3{4, 4.4, 4.f};       // int double float initialize...
    
    Test t4(4, 4.4, 4.f);       // int double float initialize...
    t4 = {1, 2, cc};            // int float char* initialize...
    
    return 0;
}

测试代码二:

template <typename T1, typename T2, typename T3> 
class my_wrapper { 
    T1 t1; 
    T2 t2; 
    T3 t3; 
public: 
    explicit my_wrapper(T1 t1_, T2 t2_, T3 t3_) : t1{t1_}, t2{t2_}, t3{t3_} {
        cout << t1_ << " " << t2_ << " " << t3_ << endl;
    }
};

// 工厂函数
template <typename T1, typename T2, typename T3>
my_wrapper<T1, T2, T3> make_wrapper(T1 t1, T2 t2, T3 t3) { 
    return my_wrapper{t1, t2, t3}; 
}

int main()
{
    my_wrapper wrapper {123, 1.23, "abc"};
    // my_wrapper<int, double, const char *> wrapper {123, 1.23, "abc"};   // 之前的写法

    auto wrapper = make_wrapper(123, 1.23, "abc");
    // auto wrapper = make_wrapper<int, double, const char *>(123, 1.23, "abc"); // 之前的写法
    
    auto x{3};
    // auto y{1,2}; // error: direct-list-initialization of ‘auto’ requires exactly one element [-fpermissive]
    auto z = {1,2};

    return 0;
}

参考:

Initialization