初始化列表中的std::array初始化列表初始化

8

虽然我非常喜欢C++11中的新功能,但有时我觉得自己错过了一些微妙之处。

初始化int数组没有问题,初始化Element2向量也没有问题,但初始化Element2数组失败了。 我认为正确的语法应该是取消注释的那行,但是我所有的初始化尝试都没有成功。

#include <array>
#include <vector>

class Element2
{
    public:
            Element2(unsigned int Input) {}
            Element2(Element2 const &Other) {}
};

class Test
{
    public:
            Test(void) :
                    Array{{4, 5, 6}},
                    Array2{4, 5},
                    //Array3{4, 5, 6}
                    Array3{{4, 5, 6}}
                    //Array3{{4}, {5}, {6}}
                    //Array3{{{4}, {5}, {6}}}
                    //Array3{Element2{4}, Element2{5}, Element2{6}}
                    //Array3{{Element2{4}, Element2{5}, Element2{6}}}
                    //Array3{{{Element2{4}}, {Element2{5}}, {Element2{6}}}}
                    {}
    private:
            std::array<int, 3> Array;
            std::vector<Element2> Array2;
            std::array<Element2, 3> Array3;
};

int main(int argc, char **argv)
{
    Test();
    return 0;
}

我已经在MinGW下的g++ 4.6.1和4.6.2上尝试过这个方法。
如何正确地初始化这个数组?是否可能?

我猜这与初始化列表没有太大关系。编辑问题以使其更加简明扼要是否合适? - rendaw
1个回答

7

正确的方法是 Array{{4, 5, 6}}。当使用聚合初始化时,不能省略大括号来初始化成员变量。唯一能够省略大括号的情况是在声明中使用以下格式:

T t = { ... }

所以在你的情况下,你需要输入所有的大括号:一个是用于std :: array本身,另一个是用于int数组。对于Array3,你的语法也是正确的,因为int可以隐式转换为Element2
在剩下被注释的代码中,Array3{{{4}, {5}, {6}}}Array3{{Element2{4}, Element2{5}, Element2{6}}}Array3{{{Element2{4}}, {Element2{5}}, {Element2{6}}}}也可以工作,但是更加冗长。然而,从概念上讲,Array3{{{4}, {5}, {6}}}会在不进行复制省略的实现上产生最少量的临时变量(我猜这不相关,但仍然很好知道),甚至比Array3{{4, 5, 6}}更少,因为对于你的Element2,你使用复制列表初始化而不是复制初始化,这样可以通过设计不产生中介临时变量。

你是说这应该可以正常工作,而 GCC 是有问题的吗?因为 OP 说所有这些变体都失败了。另外,这实际上是如何工作的,因为 std::array<Element2> 不是一个聚合体?我可以引用规范对聚合体的要求,并且 std::array<Element2> 未通过该测试。你能引用一下关于如何通过聚合初始化来初始化非聚合体的规范吗?我不是说你错了。我自由承认我从未完全阅读过 C++11 规范。同时,我想要一些证据来证明你的说法的真实性。 - Nicol Bolas
1
据我理解,std::array<T>是一个聚合体:它是一个没有用户定义构造函数的结构体 - 并且在<array>的描述中明确提到它是一个聚合体。@NicolBolas - user743382
我又仔细阅读了一遍关于聚合体的要求,显然缺少任何规定聚合体的成员不可以具有用户提供的构造函数。所以你是正确的。 - Nicol Bolas
@Ben 谢谢,不确定为什么我写了“emit”。可能是因为我做了太多的Qt编程。 - Johannes Schaub - litb
1
这段代码在我的g++ 4.7中运行良好,使用的是12月份的快照。 - rendaw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接