【问题标题】:Uniform initialization fails to copy when object has no data members当对象没有数据成员时,统一初始化无法复制
【发布时间】:2014-01-24 19:23:49
【问题描述】:

在更新一些代码以使用统一初始化时,我认为这将是现在“旧式”括号样式的现代替代品。我知道情况并非总是如此(明显的例子,vector<int>),但我偶然发现了另一个我不明白的区别。

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

int main() {
    Object o;
    Object copy{o}; // error
    Object copy2(o); // OK
}

在clang3.5下编译失败,报错:(gcc下也失败)

error: excess elements in struct initializer

Object 有两个不同的更改可以实现这一点。要么给它添加一个数据成员,要么给它一个空的拷贝构造函数体

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

我不明白为什么这些会有所作为。

【问题讨论】:

  • 添加数据成员允许对其进行聚合初始化。添加空主体使构造函数变得不平凡。
  • 即如果类是一个聚合类,聚合初始化将被执行,而不管括号初始化列表中初始化器的数量和类型。添加空主体使类成为非聚合类(因为现在 ctor 是用户提供的)。
  • 抱歉,将成员添加为公共允许对其进行聚合初始化(给出适当的转换错误)。将其添加为私有可能会影响类的属性,但我不确定。
  • @chris 事实上,如果一个类有一个私有或受保护的成员 => 它不是一个聚合。
  • “但我仍在理解统一初始化,所以我可能遗漏了一个关键概念。” 它对每种类型都有相同的形式,但语义不同.

标签: c++ c++11 copy-constructor uniform-initialization


【解决方案1】:

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

【讨论】:

  • clang (3.8) 和 g++ (6.1) 似乎都改变了上述行为,即使使用 -std=c++11 编译,OP 代码现在也可以正常编译使用这些较新的版本。这是否意味着 clang 和 g++ 以非标准方式前进到 C++17(对于 C++11)?这可能会改变某些代码的行为,例如stackoverflow.com/questions/38254106 编译器不应该担心吗?
【解决方案2】:

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

您所描述的这两项更改都会影响您的课程,使其从聚合变为非聚合。参见 C++11 (N3485) § 8.5.1/1:

聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数 (12.1),对于非静态数据成员 (9.2),没有 brace-or-equal-initializers,没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3)。

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

然后,继续第 8.5.4 节中的列表初始化,我们看到:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多