在更新一些代码以使用统一初始化时,我认为它将成为现在“旧式”括号样式的现代替代品。我知道情况并非总是如此(显而易见的例子,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
};
我不明白为什么这些应该有所作为。
答案 0 :(得分:6)
这是一个已知错误,希望在C ++ 17中修复(不适用于C ++ 14,请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1467)。您的结构是一个聚合,因此要使用{someElement}
对其进行初始化,至少需要一个数据成员,如您所发现的那样。尝试提供operator int();
,您将看到它编译。
答案 1 :(得分:3)
约翰内斯的答案很有用,但让我详细说明它为什么会出现。
您描述的两个更改都会影响您的课程,使其从聚合变为聚合。参见C ++ 11(N3485)§8.5.1/ 1:
聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),没有用于非静态数据成员的 brace-or-equal-initializers (9.2),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),也没有虚函数(10.3)。
定义为= default
的构造函数被认为不是用户定义的。
然后,在第8.5.4节中进入列表初始化,我们看到:
对象或类型T的引用的列表初始化定义如下:
- 如果T是聚合,则执行聚合初始化
然后是一堆“其他......”部分。因此,更改其中任何一个都允许调用构造函数而不是执行聚合初始化。
列表初始化定义的新建议标准(在Johannes的链接中可见)提供了列表中单个元素的优先级大小写,并且它具有(或非常接近)对象类型的类型初始化。之后,聚合初始化将成为最重要的优先事项。