当对象没有数据成员时,统一初始化无法复制

Rya*_*ing 9 c++ copy-constructor uniform-initialization c++11

在更新一些代码以使用统一初始化时,我认为它将成为现在"旧式"括号样式的现代替代品.我知道情况并非总是如此(显而易见的例子vector<int>),但我偶然发现了另一个我不理解的差异.

class Object {
    public:
        Object() = default;
        Object(const Object&) = default;
};

int main() {
    Object o;
    Object copy{o}; // error
    Object copy2(o); // OK
}
Run Code Online (Sandbox Code Playgroud)

无法在clang3.5下编译并出现错误:(在gcc下也失败)

error: excess elements in struct initializer
Run Code Online (Sandbox Code Playgroud)

这有两个不同的变化Object使这项工作.向其添加数据成员,或为其提供空复制构造函数体

class Object {
    private:
        int i; // this fixes it
    public:
        Object() = default;
        Object(const Object&) { } // and/or this fixes it as well
};
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这些应该有所作为.

Joh*_*itb 6

这是一个已知的错误,希望在C++ 17中修复(不适用于C++ 14,请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1467) .您的结构是一个聚合,因此要初始化它{someElement}需要至少有一个数据成员,如您所发现的那样.尝试提供一个operator int();,你会看到它编译.


chr*_*ris 3

约翰内斯的回答很有用,但让我详细说明一下为什么会发生这种情况。

\n\n

您描述的这两个更改都会影响您的类,使其从聚合变为非聚合。请参阅 C++11 (N3485) \xc2\xa7 8.5.1/1:

\n\n
\n

聚合是一个数组或类(第 9 条),没有用户提供的构造函数 (12.1),没有非静态数据成员的大括号或等于初始化器(9.2),没有私有或受保护的非静态数据成员 (第 11 条),没有基类(第 10 条),也没有虚函数(10.3)。

\n
\n\n

定义为 的构造函数= default被视为不是用户定义的。

\n\n

然后,进入 \xc2\xa7 8.5.4 中的列表初始化,我们看到:

\n\n
\n

T 类型的对象或引用的列表初始化定义如下:

\n\n
    \n
  • 如果T是聚合,则执行聚合初始化
  • \n
\n
\n\n

然后是一堆“否则……”部分。因此,更改其中任何一个都允许调用构造函数而不是执行聚合初始化。

\n\n

新提议的列表初始化定义标准(如约翰内斯的链接中所示)提供了列表中单个元素的优先级情况,并且它具有(或非常接近)对象类型的类型已初始化。之后聚合初始化将是最优先的。

\n