简体   繁体   English

显式默认默认构造函数和聚合

[英]Explicit defaulted default constructor and aggregates

How to explain the difference, when I compile #if 0 and #if 1 versions of the following code: 当我编译以下代码的#if 0#if 1版本时,如何解释差异:

#include <cstdlib>

struct A
{ 
    explicit A() = default; // explicitly defaulted or deleted constructors are allowed for aggregates (since C++11)
#if 1
private :
#endif
    int i;
};

int
main()
{
    A a = {};
    return EXIT_SUCCESS;
}
  • for #if 0 all is fine, compilation successful. 对于#if 0一切都很好,编译成功。
  • for #if 1 compilation failed with error message: for #if 1编译失败,错误消息:

    error: chosen constructor is explicit in copy-initialization 错误:选择的构造函数在复制初始化中是显式的

What is the difference for expression A a = {}; 表达式A a = {};什么区别A a = {}; depending on whether A is aggreagate or not? 取决于A是否是万能?

TL;DR: Clang and GCC are wrong in rejecting your code. TL; DR:Clang和GCC拒绝您的代码是错误的。 CWG 1630 ´s resolution made default-initialization well-formed regardless of the chosen default constructor being explicit or not. 无论选择的默认构造函数是否explicit CWG 1630的分辨率都使得默认初始化格式良好。


In the variation of your code in which i is private , A is not an aggregate, as these cannot have private members. i private代码的变体中, A不是聚合,因为它们不能拥有私有成员。 As long as i is public , however, A is an aggregate 1 , and no constructor is invoked since aggregate initialization is performed (see blue box), so your constructor being explicit is irrelevant. 但是,只要ipublicA就是聚合1 ,并且由于执行了聚合初始化而没有调用构造函数(参见蓝框),所以你的构造函数是explicit是无关紧要的。

在此输入图像描述

However, as soon as you introduce the private member, you necessitate value-initialization as per the red box. 但是,只要您引入私有成员,就需要根据红色框进行值初始化。 Hence [dcl.init]/(8.2) applies: 因此[dcl.init] /(8.2)适用:

在此输入图像描述

[dcl.init]/(7.1) defines default-initialization for this case: [dcl.init] /(7.1)定义了这种情况的默认初始化:

在此输入图像描述

And §13.3.1.3 gives 并且§13.3.1.3给出

For […] default-initialization, the candidate functions are all the constructors of the class of the object being initialized. 对于默认初始化,候选函数是正在初始化的对象的类的所有构造函数。

At no point is the original context - copy- or direct-initialization - considered. 在任何时候都不考虑原始上下文 - 复制或直接初始化。 (§13.3.1.7 doesn't apply either.) In fact, this is intended; (§13.3.1.7也不适用。)事实上,这是有意的; see CWG #1518 : CWG#1518

This issue is resolved by the resolution of issue 1630 : default initialization now uses 13.3.1.3 [over.match.ctor], which now permits explicit constructors for default-initialization. 问题1630的解决方案解决了这个问题默认初始化现在使用13.3.1.3 [over.match.ctor],现在允许显式构造函数进行默认初始化。

Clang and GCC (and VC++) haven't implemented the corresponding DR yet and are thus incorrect in rejecting the code in C++14 mode. Clang和GCC(以及VC ++)尚未实现相应的DR,因此在拒绝C ++ 14模式中的代码时是不正确的。


1) Your class has a user-declared constructor, but it isn't user- provided , ie not impeding your class from being an aggregate. 1)您的类具有用户声明的构造函数,但它不是用户提供的 ,即不会阻止您的类成为聚合。 Recall the definition in [dcl.init.aggr]/1: 回想一下[dcl.init.aggr] / 1中的定义:

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3). 聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM