【问题标题】:How can I initialise a member std::array of objects that don't have a default constructor?如何初始化没有默认构造函数的对象成员 std::array?
【发布时间】:2011-12-27 15:42:43
【问题描述】:

这是我遇到问题的代码:

class Foo {
public:
    Foo() :
        memberArray{Bar(1), Bar(3), Bar(2)}
    {}
    struct Bar {
        Bar(int param1) {  }
    };
private:
    std::array<Bar,3> memberArray;
//  Bar memberArray[3];    // Using a raw array like this instead compiles fine..
};

我正在使用 GCC 4.6.1,并为 c++11 进行编译。我应该如何初始化我的 std::array?

【问题讨论】:

  • @LightnessRacesinOrbit 这不是骗子......他正在尝试初始化一个成员,但该问题初始化了一个局部变量。后者可以省略大括号,但前者不能。
  • @Johannes:我从来没有说过这是一个骗局。我说这是相关的。
  • @Ligh 你没有说这是一个骗子,但你在投票支持“完全重复关闭”的 ppl 的密切投票者名单中,上面只列出了一个可能的重复项。所以我假设你同意这是一个骗局。我错过了什么吗?
  • @JohannesSchaub-litb:您错过了我评论中的问题与被欺骗投票的问题不同。

标签: c++ c++11


【解决方案1】:

由于array&lt;T, N&gt; 实际上是一个结构,所以完全大括号的版本需要{{ .. }}(内部是array&lt;T, N&gt; 对象的数组成员)。规范在这里不允许大括号省略。它只允许在表单的声明中使用它

Type var = { ... };

所以你必须使用完全大括号的语法

Foo() :
    memberArray{{Bar(1), Bar(3), Bar(2)}}
{}

这不是 GCC 错误,而是规范要求的。

【讨论】:

  • @TonyK :我们讨论的是什么是合法的语法,什么不是合法的语法,而不是编译器实现的缺陷。
  • @TonyK :是的,在一定程度上,因为它不能在那个版本的 GCC 中编译的事实仅仅表明那个版本的 GCC 中的一个错误,并且与回答。
  • @TonyK:不要把所有事情都看得太个人化——没有人会给你“坚持”。 standard 说这个答案是正确的;任何给定编译器的行为都是无关紧要的。
  • @TonyK :我不使用 C++11 编译器,但我能够阅读 规范 文本并理解它。你现在满意吗?
  • @ildjarn 是的,GCC4.7 让我的代码正确,并为 TonyK 的代码发出警告,并为 OP 的代码发出错误。至于关于 TonyK 和 OP 代码的不同行为,我提交了 GCC PR:gcc.gnu.org/bugzilla/show_bug.cgi?id=51689
【解决方案2】:

作为一种解决方法,您可以让函数返回此数组的一个实例。

#include <array>

class Foo {
public:
    Foo() :
        memberArray(makeMemberArray())
    {}
    struct Bar {
        Bar(int param1) {  }
    };
private:
    std::array<Bar,3> memberArray;
//  Bar memberArray[3];    // Using a raw array like this instead compiles fine..

    static std::array<Bar, 3> makeMemberArray() { 
      std::array<Bar,3> a = {Bar(1), Bar(2), Bar(3)}; 
      return a; 
    }
};

我认为统一初始化应该允许你正在做的事情,除非它可能不是由编译器实现的。

【讨论】:

    【解决方案3】:

    基于 Johannes Schaub - litb 的回答...至少 GCC 将允许您使用缩写语法(省略无意义的类名):

    Foo() :
        memberArray{{ {1}, {3}, {2} }}
    {}
    

    而不是

    Foo() :
        memberArray{{Bar(1), Bar(3), Bar(2)}}
    {}
    

    我个人只在初始化多态指针数组时使用第二个版本:

    Foo() :
        memberArray{{
            dynamic_cast<Bar*>(new BarA(1)),
            dynamic_cast<Bar*>(new BarB(3)),
            dynamic_cast<Bar*>(new BarC(2))
        }}
    {}
    

    【讨论】:

      【解决方案4】:

      试试这个(它适用于 g++ 4.5.2):

        Foo() :
            memberArray (std::array<Bar,3> {Bar(1), Bar(3), Bar(2)})
        {}
      

      【讨论】:

      • @ildjarn:你有点幼稚,因为我发布了工作代码,所以对我的回答投了反对票。
      • 假设我是唯一一个愿意对错误答案投反对票的人,这有点幼稚(而且你真的需要了解“工作”的实际定义)。很抱歉让您失望了。
      猜你喜欢
      • 2012-01-28
      • 2021-05-28
      • 1970-01-01
      • 2015-10-07
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      相关资源
      最近更新 更多