c++ - 不可复制类数据成员的统一初始化导致gcc错误

标签 c++ c++11 gcc language-lawyer

假设我们有以下代码:

class A {
public:
    A() = default;    
    A(const A&) = delete;
    ~A() = default;
};

class B {
public:    
    B() : a{} { }    
    A a[1];
};

int main() 
{
    B b;
}

该代码在最新的GCC 9.2,Clang 9.2和MSVC 19.22上编译。

但是,当我将默认析构函数更改为~A() { }时,GCC返回错误use of deleted function 'A::A(const A&)'。 Clang和MSVC仍然可以编译。

当我编写A的副本构造函数时,GCC会编译,但是在运行时从未调用过该构造函数。 GCC需要复制构造函数做什么?
是GCC错误吗? (我已经在GodBolt.org上尝试了所有GCC版本,出现相同的错误。)

最佳答案

这是一个GCC错误。
B的默认构造函数使用聚合初始化来初始化无初始化程序的a[dcl.init.aggr]/8:

If there are fewer initializer-clauses in the list than there are elements in a non-union aggregate, then each element not explicitly initialized is initialized as follows:

  • If the element has a default member initializer ([class.mem]), the element is initialized from that initializer.

  • Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).

  • Otherwise, the program is ill-formed.

[...]



因此,a[0]是从{}复制副本初始化的,它是copy-list-initialization。这可能是GCC开始感到困惑的地方-复制初始化不一定涉及复制构造函数。

[dcl.init.list]/3.4:

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

  • [...]

  • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

  • [...]



因此,直接使用A的默认构造函数。没有涉及复制构造函数。也不琐碎。

如果您担心C++ 11和C++ 17之间的区别,请N3337 [dcl.init.aggr]/7:

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list ([dcl.init.list]). [...]



复制初始化在这里甚至都不涉及。和N3337 [dcl.init.list]/3.1:

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

  • If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

  • [...]



没变。

关于c++ - 不可复制类数据成员的统一初始化导致gcc错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58726018/

相关文章:

c++ - 当我0-初始化一个vector时,它和calloc有同样的效果吗?

c - 需要帮助将 .c 文件编译为 shellcode

c++ - 遵循 Lynda.com c++ 教程并在 Eclipse (OSX 10.9.3) 上设置路径时遇到问题

c++ - #define Dbg(fmt,…)(0)是什么意思?警告:表情无效

c++ - 创建矩阵?

c++ - C++中调用类模板的函数模板

c - 如何从 C 程序内部或使用内联汇编获取 C 函数的大小?

c++ - 打印无符号字符指针内的值

c++ - 为什么 std::set<>::find 返回一个常量?

c++ - 模棱两可的重载函数仅参数的模板参数不同