std :: vector和std :: array初始化列表之间的区别

时间:2014-10-03 12:56:15

标签: c++ arrays c++11 stdvector initializer-list

这个C ++ 11代码对我来说很好用:

#include <iostream>
#include <vector>
#include <array>
using namespace std;

struct str {
    int first, last;
};


vector<str> fields {
    {1,2}, {3,4}, {5,6}
};

int main()
{
    for (str s : fields)
        cout << s.first << " " << s.last << endl;
}

打印出六个预期值。

但如果我将vector<str>更改为array<str,3>,gcc会给我这个错误:“std :: array'的初始化程序太多了。”

如果我改变了fields的初始化:

array<str,3> fields {
    str{1,2}, str{3,4}, str{5,6}
};

事情很顺利。

那么为什么我在使用str{1,2}时需要std::array,而在使用{1,2}时只需要std::vector

2 个答案:

答案 0 :(得分:6)

请参阅aggregate initialization上的cppreference部分。

  

聚合初始化的影响是:

     
      
  • 每个数组元素或非静态类成员,按照类定义中的数组下标/外观的顺序,从中复制初始化   初始化列表的相应子句。

  •   
  • 如果initializer子句是嵌套的braced-init-list,则相应的类成员本身就是一个聚合:aggregate   初始化是递归的。

  •   

这意味着如果你的结构中有一个聚合,例如:

struct str {
    struct asdf
    {
        int first, last;
    } asdf; 
};

asdf将由第一个嵌套的brace-init-list初始化,即{ { 1, 2 } }。您通常需要两对大括号的原因是因为嵌套的brace-init-list在std::array中初始化基础聚合(例如,T a[N])。

但是,您仍然可以像这样初始化数组:

array<str,3> fields {
    1, 2, 3, 4, 5, 6
};

或:

array<str,3> fields { {
    1, 2, 3, 4, 5, 6
} };

代替。

另一方面,list initialization涵盖了如何初始化向量。 std::vector有一个接受std::initializer_list的构造函数。

  

类型T对象的列表初始化的效果是:

     
      
  • 否则,T的构造函数分为两个阶段:

         
        
    • 所有构造函数将std::initializer_list作为唯一参数,或者作为第一个参数,如果其余参数具有   默认值,检查并通过重载决策进行匹配   针对类型std::initializer_list
    • 的单个参数   
  •   

请注意,您无法初始化矢量(例如:

vector<str> fields {
    1,2, 3,4, 5,6
};

但:

vector<int> fields {
    1,2, 3,4, 5,6
};

非常好。

答案 1 :(得分:4)

这是因为数组初始化与矢量有点不同 要初始化数组,您需要使用两个大括号 由于语法功能,如果只初始化一个对象,则可以跳过它 所以以下是可以的:

array{1,2,3} -> array{{1,2,3}}

但是在您的示例中,您初始化了多个对象,因此编译器不会添加其他大括号。使用两个括号修复了。

array<str,3> fields {{
    {1,2}, {3,4}, {5,6}
}};