鉴于下面的示例,我很惊讶地发现,尽管显式删除了默认构造函数(或者默认为默认构造函数),但仍然可以进行聚合初始化。
#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都是如此
我问这个问题的原因是,我希望更改对默认构造函数的访问会阻止公共聚合初始化
答案 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_
。