聚合初始化不支持构造函数访问

Wer*_*mus 6 c++ initialization language-lawyer aggregate-initialization c++11

鉴于下面的示例,我很惊讶地发现尽管显式删除了默认构造函数(或者默认为此),但仍然可以进行聚合初始化.

#include <iostream>

struct DefaultPrivate
{
      const int n_;
      static const DefaultPrivate& create();

    private:
      DefaultPrivate() = delete;
};

const DefaultPrivate& DefaultPrivate::create()
{
    static DefaultPrivate result{10};
    return result;
}

int main() {
    DefaultPrivate x; //Fails
    DefaultPrivate y{10};//Works
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

私有默认(或删除)构造与聚合初始化之间的关系是否未在标准中指定?

GCC 6.3和VCC 2017就属于这种情况

我问这个问题的原因是,我希望更改对默认构造函数的访问会阻止公共聚合初始化

son*_*yao 5

从 C++11 开始,对于列表初始化

如果T是聚合类型,则执行聚合初始化。

在 C++11 中,聚合是以下类型之一:

...

类类型(通常,结构或联合),具有

  • ...

  • 没有用户提供的, inherited, or explicit (since C++17)构造函数(explicitly defaulted or deleted constructors are allowed) (since C++11)

  • ...

这意味着从 C++11 开始,显式删除构造函数的类仍然被视为聚合类型,然后允许聚合初始化。

效果是:

每个direct public base, (since C++17)数组元素或非静态类成员,按照类定义中数组下标/出现的顺序,从初始值设定项列表的相应子句中复制初始化。

注意,对于DefaultPrivate y{10};在上述过程中,默认的构造函数将根本不被考虑,那么,它的声明的事实deleteprivate不会的事情。

BTW:对于执行DefaultPrivate x; 默认初始化

如果Tnon-POD (until C++11)类类型,则考虑构造函数并针对空参数列表进行重载决议。调用选定的构造函数(默认构造函数之一)为新对象提供初始值;

所以尝试使用默认构造函数但它被delete编辑然后编译失败。

如果您使用聚合初始化,例如DefaultPrivate x{};,代码也可以正常工作;并且n_值初始化(然后零初始化)为0

居住