6

鉴于下面的示例,我惊讶地发现,尽管默认构造函数被显式删除(或为此设为默认),聚合初始化仍然是可能的。

#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;
}

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

GCC 6.3 和 VCC 2017 都是这种情况

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

4

1 回答 1

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};,在上述过程中根本不会考虑默认构造函数,那么它被声明为的事实delete并不private重要。

顺便说一句:对于执行DefaultPrivate x; 默认初始化

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

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

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

居住

于 2017-10-27T09:18:32.490 回答