2014-10-03 54 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} 
}};