不可复制对象成员数组的C++成员初始化列表

不可复制对象成员数组的C++成员初始化列表,c++,constructor,initializer-list,C++,Constructor,Initializer List,我有一个对象是不可复制的,它需要一个参数作为它的构造函数: class Foo { public: Foo() = delete; Foo(const Foo &) = delete; Foo(int x); private: int member; }; Foo::Foo(int x) : member(x) { } 我有另一个类,其中包含一个这样的对象数组作为成员: class Bar { public: Bar(int a)

我有一个对象是不可复制的,它需要一个参数作为它的构造函数:

class Foo
{
  public:
    Foo() = delete;
    Foo(const Foo &) = delete;
    Foo(int x);

  private:
    int member;
};

Foo::Foo(int x) : member(x)
{
}
我有另一个类,其中包含一个这样的对象数组作为成员:

class Bar
{
  public:
    Bar(int a);

  private:
    Foo members[4];
};
假设我的对象Foo实在太大了,而且它的构造函数太复杂了,以至于临时副本或重复副本不可能存在,或者对于数组的每个项,构造函数也不可能被多次调用

如何为包含类编写构造函数以将参数传递给成员数组中的项

我试过:

Bar::Bar(int a) : members { a, a+1, a+2, a+3 }
{
}
g++表示使用已删除的函数Foo::foocont Foo&

[编辑]我也尝试过:

Bar::Bar(int a) : members { {a}, {a+1}, {a+2}, {a+3} }
{
}

正如Yksisarvinen所建议的那样。这也表示使用已删除的函数Foo::foocontfoo&,但前提是我为Foo声明了析构函数。如果没有析构函数,这将正确编译。如何为具有析构函数的类编译它?

这里有三个选项,具体取决于您实际想要执行的操作:

1.使用C++17 C++17有,这将解决这个问题

2.提供移动构造函数 编译器选择复制构造函数,因为通过声明自己的复制构造函数,可以防止生成移动构造函数。根据您的实际类,move构造函数可能可行,也可能不可行

Foo(Foo &&) = default; //or implement "stealing" of the resource here
请注意,您还应提供复制/移动赋值运算符和析构函数(无论是否为默认值)

3.将每个数组元素用大括号括起来 如果上述两个选项都无效,解决方法是将每个数组元素简单地包装在自己的大括号中

Bar::Bar(int a) : members { {a}, {a+1}, {a+2}, {a+3} }

通常,您以前的选项依赖于从int到Foo的转换。一旦编译器进行了转换,它就必须复制或移动,但是您排除了将转换的对象转换为数组,这将触发一个错误。通过将元素用大括号括起来,元素被初始化为Foo对象,而不是int以转换为Foo,并且不需要移动/复制。

这里有三个选项,具体取决于您实际想要执行的操作:

1.使用C++17 C++17有,这将解决这个问题

2.提供移动构造函数 编译器选择复制构造函数,因为通过声明自己的复制构造函数,可以防止生成移动构造函数。根据您的实际类,move构造函数可能可行,也可能不可行

Foo(Foo &&) = default; //or implement "stealing" of the resource here
请注意,您还应提供复制/移动赋值运算符和析构函数(无论是否为默认值)

3.将每个数组元素用大括号括起来 如果上述两个选项都无效,解决方法是将每个数组元素简单地包装在自己的大括号中

Bar::Bar(int a) : members { {a}, {a+1}, {a+2}, {a+3} }

通常,您以前的选项依赖于从int到Foo的转换。一旦编译器进行了转换,它就必须复制或移动,但是您排除了将转换的对象转换为数组,这将触发一个错误。通过将元素用大括号括起来,元素将被初始化为Foo对象,而不是int以转换为Foo,并且不需要移动/复制。

是否可以添加编译器错误?是否可以添加编译器错误?您好,感谢回复。选项3可以编译,但前提是Foo的析构函数是隐式的。只要我添加~Foo的声明;在有或没有定义的类中,它开始再次抱怨使用了已删除的复制构造函数。您好,谢谢您的回复。选项3可以编译,但前提是Foo的析构函数是隐式的。只要我添加~Foo的声明;在有或没有定义的类中,它开始再次抱怨使用了已删除的复制构造函数。