为什么大括号括起来的初始值设定项列表不适用于 std::array

Why do brace-enclosed initializer lists not work for std::array

本文关键字:列表 不适用 std array 适用于 起来 为什么      更新时间:2023-10-16

我想用对象列表初始化一个向量或数组。它适用于向量,但不适用于数组:

struct Widget
{
    string name;
    vector<int> list;
};
struct Object
{
    string name;
    vector<int> list;
    Object(string _name, vector<int> _list) : name(_name), list(_list) { }
};
int main()
{
    const vector<Widget> vw = {
        {"vw1", {1,2,3}},
        {"vw2", {1,2,3}} };
    const array<Widget,2> aw = {
        {"aw1", {1,2,3}},
        {"aw2", {1,2,3}} };
    const vector<Object> vo = {
        {"vo1", {1,2,3}},
        {"vo2", {1,2,3}} };
    const array<Object,2> ao = {
        {"ao1", {1,2,3}},
        {"ao2", {1,2,3}} };
    return 0;
}

来自叮当的错误:

widget.cpp:36:9: error: excess elements in struct initializer
        {"aw2", {1,2,3}} };
        ^~~~~~~~~~~~~~~~
widget.cpp:41:10: error: no viable conversion from 'const char [4]' to 'Object'
        {"ao1", {1,2,3}},
         ^~~~~
widget.cpp:41:17: error: no matching constructor for initialization of 'Object'
        {"ao1", {1,2,3}},
                ^~~~~~~

矢量和数组之间有什么区别,这会阻止数组类型支持此语法?

这是有效的解决方案 - 数组需要双括号。

int main()
{
    const vector<Widget> vw = {
        {"vw1", {1,2,3}},
        {"vw2", {1,2,3}} };
    const array<Widget,2> aw = {{
        {"aw1", {1,2,3}},
        {"aw2", {1,2,3}} }};
    const vector<Object> vo = {
        {"vo1", {1,2,3}},
        {"vo2", {1,2,3}} };
    const array<Object,2> ao = {{
        {"ao1", {1,2,3}},
        {"ao2", {1,2,3}} }};
    return 0;
}

为什么?

http://en.cppreference.com/w/cpp/container/array

std::array 是一个封装固定大小数组的容器。此容器是一个聚合类型,其语义与将 C 样式数组 T[N] 作为其唯一非静态数据成员的结构相同。与 C 样式数组不同,它不会自动衰减到 T*。作为聚合类型,可以使用聚合初始化进行初始化,最多给出 N 个可转换为 T:std::array a = {1,2,3};的初始值设定项。

理论实现(现实中比较复杂(

template <typename T, size_t size> 
struct array  
{
  T data[size]; 
}

因此,第一个大括号是聚合-初始化数组对象本身,第二个大括号是聚合初始化内部"遗留 C 样式"数组。

在示例中添加另一对大括号将使它们能够正常工作:

int main()
{
    const std::array<Widget,2> aw = {
        {
            {"aw1", {1, 2, 3}},
            {"aw2", {1, 2, 3}}
        }
    };
    const std::array<Object, 2> ao = {
        {
            {"ao1", {1, 2, 3} },
            {"ao2", {1, 2, 3} }
        }
    };
    cout << aw[0].name << " " << aw[1].list[1] << endl;
    cout << ao[0].name << " " << ao[1].list[1] << endl;
    return 0;
}

将给出输出:

aw1 2
ao1 2

需要额外的大括号对,因为std::array本身没有构造函数,并且只是使用聚合初始化而不是列表初始化。

在实现方面,std::array由一个内部项组成,即N元素的真正底层数组。 因此,我们需要额外的大括号,因此我们使用一个元素(在您的示例中是两个元素的数组(初始化std::array