Cod*_*cks 11 c++ vector curly-braces uniform-initialization c++11
C++ 11
程序初始化一个vector
名为s的命名myVec
,int
vector
然后使用一个循环打印出每个内部vector
元素.但是当我试图看到当我使用额外的花括号时会发生什么,我得到了意想不到的结果.以下内容也适用于此LiveWorkSpace,以便在编译器之间轻松切换.g++ 4.8.0
只汇编到myVec[5]
.clang++ 3.2
汇编一切:
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>> myVec =
{
/* myVec[0] */ {1, 2},
/* myVec[1] */ {},
/* myVec[2] */ {{}},
/* myVec[3] */ { {}, {} },
/* myVec[4] */ { {}, {}, {} },
/* myVec[5] */ {{{}}}
/* myVec[6] */ // , { {{}}, {{}} } // g++ 4.8.0 COMPILER ERROR
/* myVec[7] */ // , {{{{}}}} // g++ 4.8.0 COMPILER ERROR
/* myVec[8] */ // , { {{{}}}, {{{}}} } // g++ 4.8.0 COMPILER ERROR
};
// loop for printing
for (unsigned int i = 0; i < myVec.size(); ++i)
{
std::cout << "myVec[" << i << "]: ";
for (unsigned int j = 0; j < myVec.at(i).size(); ++j)
{
std::cout << myVec.at(i).at(j) << ", ";
}
std::cout << std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
实际g++ 4.8.0
产量:
myVec[0]: 1, 2,
myVec[1]:
myVec[2]: 0,
myVec[3]: 0, 0,
myVec[4]: 0, 0, 0,
myVec[5]: 0,
Run Code Online (Sandbox Code Playgroud)
分析:
myVec[0]
:{1, 2}
:
得到预期的输出.
myVec[1]
:{}
:
得到预期的输出.
myVec[2]
:{{}}
:
这是一个矢量int
0
.内部括号初始化int
为0
.
myVec[3]
:{ {}, {} }
:
两个内括号初始化int
每个0
.
myVec[4]
:{ {}, {}, {} }
:
三个内括号初始化int
每个0
.
myVec[5]
:{{{}}}
:
我想添加另一组花括号来myVec[2]
看看在获得编译器错误之前我可以添加大括号.我不明白为什么这个编译以及为什么它的元素打印为0
.
例如,int j = {}
初始化j
为0
.vector<vector<int>> v = { {{}} }
初始化最里面{}
的int
0
,使它等同于vector<vector<int>> v = { {0} }
.那么,vector<vector<int>> u = { {{{}}} }
它是什么以及为什么要编译?
假设myVec[6]
:{ {{}}, {{}} }
:
按照与上面相同的模式,我想制作一个包含两组双花括号的矢量.但这不能编译,我不明白为什么这会打破给我多个零的模式.
假设myVec[7]
:{{{{}}}}
:
我想添加另一组花括号来myVec[5]
看看在获得编译器错误之前我可以添加大括号.我不明白为什么这会破坏模式并且不会编译.
假设myVec[8]
:{ {{{}}}, {{{}}} }
:
我想扩展myVec[7]
到制作带有两组三重括号的矢量.我不明白为什么这也不编译.
如果一切都要myVec[5]
编译,为什么不休息呢?
尝试编译这段代码。它应该解释你的问题:
\n\nint i = {}; // initializes i to int()\nint j = {{}}; // fails to compile\n
Run Code Online (Sandbox Code Playgroud)\n\n为什么{{{}}}
在你的代码中被接受似乎是一个 gcc bug(需要澄清)与 ctor 的处理方式相关:
struct foo {\n foo( std::initializer_list<int> ) {}\n};\nvoid f()\n{\n foo bar1( {{{}}} ); // compiles fine\n foo bar2 = {{{}}}; // compiles fine\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n编辑(感谢 Johannes Schaub) - 删除复制因子使第一个变体无法编译:
\n\nstruct foo {\n foo( std::initializer_list<int> ) {}\n foo( const foo& ) = delete;\n};\nvoid f()\n{\n foo bar1( {{{}}} ); // fails to compile: use of deleted function \xe2\x80\x98foo::foo(const foo&)\xe2\x80\x99\n foo bar2 = {{{}}}; // still compiles, neither deleting move ctor, nor assignment operator does not affect that, is copy ctor of std::initializer_list involved?\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n对于成员函数它失败:
\n\nstruct foo {\n void moo( std::initializer_list<int> ) {}\n};\nvoid f()\n{\n foo bar;\n bar.moo( {{{}}} ); // fails to compile\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n此代码也失败:
\n\nstd::initializer_list<int> l = {{{}}}; // fails to compile\n
Run Code Online (Sandbox Code Playgroud)\n\n同样的情况 ctor 与 std::vector 的成员函数:
\n\nvoid f()\n{\n std::vector<int> v( {{{}}} ) // compiles fine;\n v.assign( {{{}}} ); // fails to compile\n};\n
Run Code Online (Sandbox Code Playgroud)\n\ngcc 版本 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1)
\n