当对象没有数据成员时,统一初始化无法复制 [英] Uniform initialization fails to copy when object has no data members

查看:130
本文介绍了当对象没有数据成员时,统一初始化无法复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

int main(){
对象o;
对象副本{o}; // error
Object copy2(o); // OK
}

无法在clang3.5下编译,失败在gcc下)

 错误:struct initializer中的多余元素

Object 有两个不同的更改,使这项工作。可以向其中添加数据成员,也可以给它一个空副本构造函数体

  class Object {
private:
int i; // this fixes it
public:
Object()= default;
Object(const Object&){} //和/或这也修复了它
};

我不明白为什么会产生影响。



这两个变化都是非常有用的你描述的影响你的类,通过使它从一个聚合,而不是一个聚合。参见C ++ 11(N3485)§8.5.1 / 1:


聚合是数组或类没有用户提供的构造函数(12.1),没有非静态数据成员(9.2)的 brace-or-equal-initializers ,没有私有或受保护的非静态数据成员


一个构造函数,定义为 =



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


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




  • 如果T是汇总,则执行汇总初始化


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



用于列表初始化定义的新提议的标准(在约翰内斯链接中可见)提供列表中单个元素的优先化情况,并且它具有类型(或真的接近)被初始化的对象的类型。之后,聚合初始化将是最高优先级。


In updating some code to use uniform initialization, I thought it would be a drop-in modern substitue for the now "old style" parentheses style. I know this isn't always the case (obvious example, vector<int>) but I've stumbled over another difference that I don't understand.

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

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

fails to compile under clang3.5 with the error: (also fails under gcc)

error: excess elements in struct initializer

There are two different changes to Object that make this work. Either adding a data member to it, or giving it an empty copy constructor body

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

I don't see why these should make a difference.

解决方案

Johannes's answer is useful, but let me elaborate on why it currently happens.

Both of the changes you describe affect your class by making it go from an aggregate to not an aggregate. See C++11 (N3485) § 8.5.1/1:

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

A constructor with a definition of = default is considered not user-defined.

Then, going down to list-initialization in § 8.5.4, we see:

List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed

And then a bunch of "Otherwise..." sections. Thus, changing either of these allows a constructor to be called instead of performing aggregate initialization.

The new proposed standardese for the list-initialization definition (as viewable in Johannes's link) provides a prioritized case of a single element in the list, and it having a type of (or really close to) the type of the object being initialized. Aggregate initialization would then be top priority after that.

这篇关于当对象没有数据成员时,统一初始化无法复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆