大括号初始化

并不总是需要为 class 定义构造函数,特别是相对比较简单的类。 用户可以使用统一初始化来初始化 classstruct 的对象,如下面的示例所示:

// no_constructor.cpp
// Compile with: cl /EHsc no_constructor.cpp
#include <time.h>

// No constructor
struct TempData
{
    int StationId;
    time_t timeSet;
    double current;
    double maxTemp;
    double minTemp;
};

// Has a constructor
struct TempData2
{
    TempData2(double minimum, double maximum, double cur, int id, time_t t) :
       stationId{id}, timeSet{t}, current{cur}, maxTemp{maximum}, minTemp{minimum} {}
    int stationId;
    time_t timeSet;
    double current;
    double maxTemp;
    double minTemp;
};

int main()
{
    time_t time_to_set;

    // Member initialization (in order of declaration):
    TempData td{ 45978, time(&time_to_set), 28.9, 37.0, 16.7 };

    // When there's no constructor, an empty brace initializer does
    // value initialization = {0,0,0,0,0}
    TempData td_emptyInit{};

    // Uninitialized = if used, emits warning C4700 uninitialized local variable
    TempData td_noInit;

    // Member declaration (in order of ctor parameters)
    TempData2 td2{ 16.7, 37.0, 28.9, 45978, time(&time_to_set) };

    return 0;
}

如果 classstruct 没有构造函数,请按 class 中声明的成员的顺序提供列表元素。 如果 class 具有构造函数,请按参数顺序提供元素。 如果类型具有隐式或显式声明的默认构造函数,你可以使用大括号初始化(具有空大括号)对其进行调用。 例如,可通过使用空大括号和非空大括号初始化来初始化以下 class

#include <string>
using namespace std;

class class_a {
public:
    class_a() {}
    class_a(string str) : m_string{ str } {}
    class_a(string str, double dbl) : m_string{ str }, m_double{ dbl } {}
double m_double;
string m_string;
};

int main()
{
    class_a c1{};
    class_a c1_1;

    class_a c2{ "ww" };
    class_a c2_1("xx");

    // order of parameters is the same as the constructor
    class_a c3{ "yy", 4.4 };
    class_a c3_1("zz", 5.5);
}

如果类具有非默认构造函数,则类成员在大括号初始值设定项中的显示顺序是对应参数在构造函数中的显示顺序,而不是成员的声明顺序(如上一示例中的 class_a 一样)。 否则,如果类型没有声明的构造函数,则成员初始值设定项必须按声明的顺序显示在大括号初始值设定项中。 在这种情况下,可以根据需要初始化尽可能多的公共成员,但不能跳过任何成员。 以下示例演示了在无声明的构造函数时在大括号初始化中使用的顺序:

class class_d {
public:
    float m_float;
    string m_string;
    wchar_t m_char;
};

int main()
{
    class_d d1{};
    class_d d1{ 4.5 };
    class_d d2{ 4.5, "string" };
    class_d d3{ 4.5, "string", 'c' };

    class_d d4{ "string", 'c' }; // compiler error
    class_d d5{ "string", 'c', 2.0 }; // compiler error
}

如果默认构造函数已显式声明,但标记为“已删除”,则无法使用空大括号初始化:

class class_f {
public:
    class_f() = delete;
    class_f(string x): m_string { x } {}
    string m_string;
};
int main()
{
    class_f cf{ "hello" };
    class_f cf1{}; // compiler error C2280: attempting to reference a deleted function
}

可以在通常进行初始化的任何位置使用大括号初始化 - 例如,初始化为函数参数或返回值,或使用 new 关键字初始化:

class_d* cf = new class_d{4.5};
kr->add_d({ 4.5 });
return { 4.5 };

/std:c++17 模式和更高版本中,空大括号初始化的规则略有限制。 请参阅派生构造函数和扩展聚合初始化

initializer_list 构造函数

initializer_list 类表示可以在构造函数和其他上下文中使用的指定类型的对象的列表。 您可通过使用大括号初始化构造 initializer_list:

initializer_list<int> int_list{5, 6, 7};

重要

若要使用此类,必须包括 <initializer_list> 标头。

可以复制 initializer_list。 在这种情况下,新列表的成员是对原始列表成员的引用:

initializer_list<int> ilist1{ 5, 6, 7 };
initializer_list<int> ilist2( ilist1 );
if (ilist1.begin() == ilist2.begin())
    cout << "yes" << endl; // expect "yes"

标准库容器类以及 stringwstringregex 具有 initializer_list 构造函数。 以下示例演示如何使用这些构造函数执行大括号初始化:

vector<int> v1{ 9, 10, 11 };
map<int, string> m1{ {1, "a"}, {2, "b"} };
string s{ 'a', 'b', 'c' };
regex rgx{ 'x', 'y', 'z' };

另请参阅

类和结构
构造函数