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

时间:2017-10-27 09:06:35

标签: c++ c++11 initialization language-lawyer aggregate-initialization

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

#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都是如此

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

1 个答案:

答案 0 :(得分:4)

从C ++ 11开始,list initialization

  

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

使用C ++ 11,aggregate是以下类型之一:

  

...

     

类类型(通常是struct或union),具有

     
      
  • ...

  •   
  • 没有用户提供的, 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和{{1}赢得了。

BTW:执行private default initialization

  

如果DefaultPrivate x;T类类型,则考虑构造函数并对空参数列表进行重载解析。选择的构造函数(它是默认构造函数之一)被调用以提供新对象的初始值;

因此尝试使用默认构造函数,但它non-POD (until C++11)编辑失败。

如果使用聚合初始化,例如delete,代码也可以正常工作; DefaultPrivate x{};value initialized(然后zero initialized)为n_

LIVE