c++ - 显式默认的默认构造函数和聚合

标签 c++ c++11 constructor c++14 default-constructor

当我编译以下代码的 #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 一切正常,编译成功。
  • for #if 1 编译失败并显示错误消息:

    error: chosen constructor is explicit in copy-initialization

表达式 A a = {}; 取决于 A 是否聚合有什么区别?

最佳答案

TL;DR:Clang 和 GCC 拒绝您的代码是错误的。 CWG 1630无论选择的默认构造函数是 explicit 与否。


iprivate 的代码变体中,A 不是聚合,因为它们不能有私有(private)成员。但是,只要 ipublicA 就是一个聚合1,并且由于聚合,所以不会调用构造函数执行初始化(见蓝色框),所以你的构造函数是 explicit 是无关紧要的。

enter image description here

但是,一旦您引入私有(private)成员,您就需要按照红框进行值初始化。因此 [dcl.init]/(8.2) 适用:

enter image description here

[dcl.init]/(7.1) 为这种情况定义了默认初始化:

enter image description here

§13.3.1.3 给出了

For […] default-initialization, the candidate functions are all the constructors of the class of the object being initialized.

在任何时候都不会考虑原始上下文 - 复制或直接初始化。 (§13.3.1.7 也不适用。)事实上,这是有意的;见 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.

Clang 和 GCC(和 VC++)还没有实现相应的 DR,因此拒绝 C++14 模式下的代码是不正确的。


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).

关于c++ - 显式默认的默认构造函数和聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33522985/

相关文章:

c++ - 单例类无法处理多个文件

c++ - -ffast-math 可以安全地用于典型项目吗?

c++ - 通用项目的 Qt Creator c++11 语法突出显示

c++ - C++17 会支持更简单的基于范围的 For 循环吗?

c++ - 带或不带括号实例化类?

c++ - GNU make - $(MAKEFILES) 中的 makefile 中的规则未被读取/确认

C++ 深度优先搜索 (DFS) 实现

c++ - 在这种情况下,带有 memory_order_seq_cst 的原子读操作读取哪个值?

java - 防止进一步实例化 Java 类的最佳实践

c++ - 构造函数 "=default"和 C++ 中编译器生成的构造函数有什么区别?