std::array初始化代碼編譯出現too many initializers錯誤的原因?
如下面代碼所示,array&
a1 = {{"a"}, {"b"}};會編譯不通過,提示: std::array&
』的初始值設定項太多
array&a1 = {{"a"}, {"b"}}; compile error: to many initializers 但是&
其他類型&有的類型的初始化可以去掉最外層的大括弧。array&用gcc編譯出錯但是VS2015不會報錯。請問是什麼原因? 測試環境Windows 10 Pro x64 visual studio 2015 / Cgywin x86_64 g++ 5.4.0 -std=c++11
#include &
#include &
#include &
#include &
#include &
#include &
using namespace std;struct Person
{
string name;
};
bool operator==(const Person l, const Person r) { return l.name == r.name; }#define CHECK_EQUAL(x, y) do {
cout &<&< #x " == " #y " : " &<&< ((x == y) ? "true" : "false") &<&< endl; } while (false) int main() { int i1 = 123; int i2 = { 123 }; CHECK_EQUAL(i1, i2); //i1 == i2 : true Person p1 = { "a" }; Person p2 = { { "a" } }; CHECK_EQUAL(p1, p2); //p1 == p2 : true //array&a1 = {{"a"}, {"b"}}; //compile error: to many initializers
array&a2 = { { { "a" },{ "b" } } };
array&a3 = { { { { "a" } },{ { "b" } } } };
CHECK_EQUAL(a2, a3); //a2 == a3 : true#ifdef WIN32
array&a4 = {1, 2}; //gcc compile error: to many initializers
array&a5 = { { 1, 2 } };
array&a6 = {{{1}, {2}}}; //gcc compile error: 類型『int』的標量初始化帶花括弧
CHECK_EQUAL(a4, a5); //a7 == a8 : true
CHECK_EQUAL(a4, a6); //a8 == a9 : true
#endifarray&
a7 = { "1", "2" };
array&a8 = { { "1", "2" } };
array&a9 = { { { "1" },{ "2" } } };
CHECK_EQUAL(a7, a8); //a7 == a8 : true
CHECK_EQUAL(a8, a9); //a8 == a9 : truevector&
v1 = { { "a" },{ "b" } };
vector&v2 = { { { "a" } },{ { "b" } } };
vector&v3 = { { { { "a" } },{ { "b" } } } };
CHECK_EQUAL(v1, v2); //v1 == v2 : true
CHECK_EQUAL(v1, v3); //v1 == v3 : true
return 0;
}
在C++11引入initializer_list後,由於C++11標準(§8.5.1/11)中規定
In a declaration of the form
T x = { a };
braces can be elided in an initializer-list as follows.
所以當出現
T x = { a };
的時候,有這麼幾種情況:
1.T是一個聚合類
這種情況下,程序會把大括弧里的值按類內成員變數的定義順序依次賦值,如果參數過多,會報錯「too many initializers」
struct node {
int a, b;
};
int main() {
node c = {1, 2}; // OK, c.a = 1, c.b = 2
node d = {1, 2, 3}; // error: too many initializers for node
}
2.T有用戶自定義的構造函數
這時候,這句話等價於
T x(a);
也就是說,程序會調用T里和a相匹配的構造函數來構造x
#include &
struct node {
int a, b;
node (int a) {
this-&>a = a;
this-&>b = 2;
}
};
int main() {
node s = {1};
std::cout &<&< s.a &<&< &<&< s.b; // 1 2
}
3.T有一個以initializer_list為參數的構造函數
這時候,根據一開始提到的標準里的規定,事實上,這句話等價於
T x = {{a}};
和2一樣,程序會調用T里以initializer_list為參數的那個構造函數來構造x,其中initializer_list里的參數為a
#include &
#include &
struct node {
int a, b;
node (const std::initializer_list&
this-&>a = 0;
this-&>b = 0;
for (auto i : c) {
this-&>a = this-&>b;
this-&>b = i;
}
}
};
int main() {
node s = {1, 2, 3, 4, 5};
std::cout &<&< s.a &<&< &<&< s.b; // 4 5
}
4.2和3同時存在
T里既有一個以initializer_list為參數的構造函數,也有另外的用戶自定義的構造函數,這時候,程序優先按3來構造,典型的例子就是vector
vector&
這樣的初始化是讓a里一開始就有2個元素1、2,而不是只有1個為2的元素
===
這是4種比較基本的情況,但事實上,還有可能有更多的奇怪的東西,就比如現在提出的這個問題
在說這個問題之前,首先要指出的是,array和其他容器並不一樣,它是一個聚合類,也就是說,它沒有用戶自定義的構造函數,所以分析的時候得按1來處理,你可以把它看成
template&
class array {
public:
T __array[len];
.... // 一些成員函數
};
然後回到問題來,一個一個看
===
array&
a1 = {{"a"}, {"b"}}; //compile error: too many initializers
根據1,它會把{"a"}, {"b"}按定義順序依次給array里的成員變數賦值,它在把{"a"}賦值給__array後(__array[2] = {"a"};),對於{"b"},它找不到可以賦值的成員,所以會報錯
不過你有可能會問,既然它是聚合類,那為什麼還可以直接像下面這樣子呢?
array&
a7 = { "1", "2" };
還是根據一開始提到的標準里的規定,所以大括弧省略掉了,具體例子可以看給出的參考的第一個鏈接,其實就和C語言里定義二維數組一樣,你可以寫成
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
也可以不寫裡面的大括弧,直接寫
int a[2][3] = {1, 2, 3, 4, 5, 6};
而題主說
但是其他類型的初始化可以去掉最外層的大括弧
事實上其他類型也是不行的,只是你寫的和這個不一樣所以沒報錯,你要是寫成和這個一樣的形式:
array&
a7 = { {"1"}, {"2"} };
也是會報錯的
===
array&
a4 = {1, 2}; //gcc compile error: to many initializers
在我電腦上沒有出現報錯,按理來說應該也不會報錯,題主可以提供一下更詳細的信息
===
array&
a6 = {{{1}, {2}}}; //gcc compile error: 類型『int』的標量初始化帶花括弧
這個我也沒有查到具體的原因,但經測試發現,只有基本類型會報錯,而且既然VS2015不會報錯,而gcc報錯,那這有可能是個UB
參考:
When can outer braces be omitted in an initializer list?
Why is the C++ initializer_list behavior for std::vector and std::array different?
Ignoring GCC amp;quot;error: braces around scalar initializer for typeamp;quot; errors. Make them warnings
推薦閱讀:
※【遊戲框架系列】用C++畫光(二)——矩形
※使用 AsyncListUtil 優化 RecyclerView
※《奧日與黑暗森林》這樣的遊戲主要需要哪些技術,幾個人的小團隊能實現嗎?
※[譯] 閱讀 NodeJS 文檔,我學到了這 19 件事情
※【偽教程】手把手教你成為matlab作曲家