2014-10-03 36 views
7

这个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

回答

6

请参阅cppreference关于aggregate initialization的章节。

The effects of aggregate initialization are:

  • Each array element or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

  • If the initializer clause is a nested braced-init-list, the corresponding class member is itself an aggregate: aggregate initialization is recursive.

这意味着,如果你有你的结构内的聚集,如:

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

asdf将第一嵌套的大括号初始化列表初始化,即{ { 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

The effects of list initialization of an object of type T are:

  • Otherwise, the constructors of T are considered, in two phases:

    • All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list

请注意,您将无法初始化您的载体(像这样:

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

但:

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

是完全没有

4

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

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

但在你的例子中,你初始化多个对象,所以编译器不会增加额外的支撑。使用两个大括号修复了这个问题。

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