如何初始化一个没有默认构造函数的对象成员std::array?

5
这是我遇到问题的代码:

以下是我遇到问题的代码:

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?


相关链接:http://stackoverflow.com/questions/8646088/how-can-i-initialise-a-member-array-of-objects-that-dont-have-a-default-constuc - Lightness Races in Orbit
@LightnessRacesinOrbit 这不是重复的问题...他试图初始化一个成员,但那个问题初始化了一个局部变量。对于后者,大括号可以省略,但对于前者则不行。 - Johannes Schaub - litb
@Ligh,你没有说这是重复的,但你在投票人中列出了“关闭为完全重复”的人,并且只有一个可能的重复项在上面列出。所以我认为你同意这是一个重复项。我错过了什么吗? - Johannes Schaub - litb
@JohannesSchaub-litb:你错过了我评论中的问题与被重复投票的问题不同。 - Lightness Races in Orbit
这个回答解决了你的问题吗?[如何初始化一个std :: array <T,2>,其中T不可复制且无默认构造函数?](https://dev59.com/gZnga4cB1Zd3GeqPXl0K) - user202729
显示剩余3条评论
5个回答

6

由于array<T, N>实际上是一个结构体,因此完全使用大括号的版本需要{{ .. }}(内部的大括号用于array<T, N>对象的数组成员)。规范在这里不允许省略大括号。它只允许在形式为的声明中省略

Type var = { ... };

因此您必须使用完全括号语法。
Foo() :
    memberArray{{Bar(1), Bar(3), Bar(2)}}
{}

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

1
@TonyK:是的,在某种程度上是这样,因为它在那个版本的GCC中无法编译仅仅表明那个版本的GCC存在一个错误,而不影响答案的有效性。 - ildjarn
2
@TonyK:不要把一切都太当成个人问题——没有人在责备你。标准规定这个答案是正确的;任何编译器的行为都是无关紧要的。 - ildjarn
1
@TonyK:我没有使用C++11编译器,但我能够阅读“规范性”文本并理解它。现在你满意了吗? - ildjarn
1
@ildjarn 是的,GCC4.7可以正确编译我的代码,并对TonyK的代码发出警告,对OP的代码则报错。至于TonyK和OP代码之间不同的行为,我已经提交了一个GCC PR:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51689 - Johannes Schaub - litb
1
@TonyK:如果你真的那么实际,你应该自己阅读标准,而不是依赖现有(可能不足)的实现来试图证明你的观点。;-] - ildjarn
显示剩余19条评论

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; 
    }
};

我认为统一初始化语法允许你所做的操作,但编译器可能没有实现。


0

在 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))
    }}
{}

0
#include <stdio.h>
#include <array>
#include <iostream>

void test1(){ printf("hello 0\n");}
void test2(){printf("hello 1\n");}
void test3(){printf("hello 2\n");}



typedef void (*functionPointerType)(); //from fastled demoreel100 was   typedef void (*SimplePatternList[])();

    void (*functptr[])() = { test1, test2, test3 } ; //classic way
    std::array<functionPointerType, 3> funcList{ {test1, test2, test3} }; //  double-braces required in C++11 prior to




class FuncContainClass {
public:
std::array<functionPointerType, 3> funcList; 


};

FuncContainClass funcClass;

int main()
{

funcClass.funcList[1] = &test2;
funcClass.funcList[1]();



functptr[0]();

std::cout << funcList.size() << std::endl;
funcList[1]();
    return 0;
}

`

我发现这篇文章是因为我只是想要一个std::array的函数,但我认为我也找到了解决这个问题的方法。我发现如果我创建一个函数指针的typeDef,它就可以工作了。

-5
尝试这个(它适用于g++ 4.5.2):
  Foo() :
      memberArray (std::array<Bar,3> {Bar(1), Bar(3), Bar(2)})
  {}

1
@ildjarn:你这样做有点幼稚,因为我发布了可行的代码而对我的答案进行了负面评价。 - TonyK
4
你觉得我是唯一一个愿意踩一个错误回答的人,这有点孩子气(而且你真的需要学习“有效”的实际定义)。很抱歉让你失望了。 - ildjarn

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