整数向量向量的统一初始化

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.内部括号初始化int0.

myVec[3]:{ {}, {} }:

两个内括号初始化int每个0.

myVec[4]:{ {}, {}, {} }:

三个内括号初始化int每个0.

myVec[5]:{{{}}}:

我想添加另一组花括号来myVec[2]看看在获得编译器错误之前我可以添加大括号.我不明白为什么这个编译以及为什么它的元素打印为0.

例如,int j = {}初始化j0.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]编译,为什么不休息呢?

Sla*_*ica 4

尝试编译这段代码。它应该解释你的问题:

\n\n
int i = {};   // initializes i to int()\nint j = {{}}; // fails to compile\n
Run Code Online (Sandbox Code Playgroud)\n\n

为什么{{{}}}在你的代码中被接受似乎是一个 gcc bug(需要澄清)与 ctor 的处理方式相关:

\n\n
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\n
struct 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\n
struct 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\n
std::initializer_list<int> l = {{{}}}; // fails to compile\n
Run Code Online (Sandbox Code Playgroud)\n\n

同样的情况 ctor 与 std::vector 的成员函数:

\n\n
void f()\n{\n    std::vector<int> v( {{{}}} ) // compiles fine;\n    v.assign( {{{}}} ); // fails to compile\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

gcc 版本 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1)

\n