【发布时间】:2014-12-28 09:58:38
【问题描述】:
Why can't I initialise an array of objects if they have private copy constructors? 上的现有问题专门针对 C++03。我从那个问题中知道我正在尝试做的事情在 C++03 中是不允许的,但我认为在 C++11 中应该是可能的
我有一个不可移动的类(称为子类),我需要在另一个类的构造函数中初始化一个子类数组(称为父类)。 “不可移动”是指子对象的地址在该对象的生命周期内必须保持不变。这样做的正确方法是什么?
使用 C++11,我尝试了以下方法:
class Child
{
public:
Child (int x) {}
~Child () {}
Child (const Child &) = delete;
};
class Parent
{
public:
Parent () : children {{5}, {7}} {}
private:
Child children[2];
};
这段代码在 Clang 3.5.0 中编译得很好,但是 GCC 4.9.1 抱怨我正在尝试使用已删除的复制构造函数:
test.cc: In constructor ‘Parent::Parent()’:
test.cc:13:35: error: use of deleted function ‘Child::Child(const Child&)’
Parent () : children {{5}, {7}} {}
^
test.cc:7:5: note: declared here
Child (const Child &) = delete;
^
我已经了解了复制初始化和直接初始化之间的区别(例如here 和here),并且我想避免使用直接初始化来调用复制构造函数。我的语法错了吗?这是 GCC 中的错误吗?还是我试图做的事情是不可能的?
【问题讨论】:
-
在我看来这是一个 clang 错误,而不是 gcc 错误。如果您将代码更改为
children {Child{5}, Child{7}},clang 将无法编译代码,它的行为应该与您发布的内容相同。一种解决方法是使用vector并放置Child对象。 -
g++ 以
Child children[2] { {5}, {7} };成功,这应该与 ctor 初始化程序列表中出现相同初始化程序的版本相同;两者都包含在 [dcl.init.list]/3 -
通读初始化部分,这段代码似乎是正确的;
children[2] = { {5}, {7} }表示children[0]是从{5}复制初始化的,即它与Child c = { 5 };相同,并且再次由[dcl.init.list] 覆盖,它调用c的构造函数,该构造函数采用@ 987654336@(不涉及副本)。 -
@Praetorian:
children {Child {5}, Child {7}}是不同的,我想。将Child {5}放在大括号内会强制编译器(名义上)创建一个临时对象,然后将其复制以初始化数组。 -
创建gcc.gnu.org/bugzilla/show_bug.cgi?id=63707。我们将看看 GCC 开发人员怎么说。
标签: c++ arrays c++11 gcc clang