聚合初始化不支持构造函数访问[重复]
Posted
技术标签:
【中文标题】聚合初始化不支持构造函数访问[重复]【英文标题】:Aggregate initialization does not uphold constructor access [duplicate] 【发布时间】:2018-04-08 20:12:39 【问题描述】:鉴于下面的示例,我惊讶地发现尽管默认构造函数被显式删除(或为此设为默认),聚合初始化仍然可能。
#include <iostream>
struct DefaultPrivate
const int n_;
static const DefaultPrivate& create();
private:
DefaultPrivate() = delete;
;
const DefaultPrivate& DefaultPrivate::create()
static DefaultPrivate result10;
return result;
int main()
DefaultPrivate x; //Fails
DefaultPrivate y10;//Works
return 0;
标准中未指定私有默认(或删除)构造和聚合初始化之间的关系吗?
GCC 6.3 和 VCC 2017 都是这种情况
我问这个问题的原因是,我希望更改对默认构造函数的访问会阻止公共聚合初始化
【问题讨论】:
【参考方案1】:来自 C++11,对于 list initialization,
如果
T
是聚合类型,则执行聚合初始化。
对于 C++11,aggregate 是以下类型之一:
...
类类型(通常是结构或联合),具有
...
没有用户提供的
, 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 y10;
,在上述过程中根本不会考虑默认构造函数,那么声明为delete
和private
的事实就无关紧要了。
顺便说一句:对于DefaultPrivate x;
default initialization 执行,
如果
T
是non-POD (until C++11)
类类型,则考虑构造函数并对其进行针对空参数列表的重载决议。调用选择的构造函数(默认构造函数之一)为新对象提供初始值;
所以尝试使用默认构造函数但它是delete
ed 然后编译失败。
如果你使用聚合初始化,比如DefaultPrivate x;
,代码也可以正常工作;而n_
将是value initialized(然后是zero initialized)作为0
。
LIVE
【讨论】:
是的,类型是聚合的,但它是私人意义上的聚合,或者我希望是这样,否则我不会在标题中使用聚合 @WernerErasmus 答案已修改。关键是这种情况下不会考虑构造函数,所以没关系。以上是关于聚合初始化不支持构造函数访问[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Boost(或其他库)是不是提供了一种将“无构造函数”类的名称提升为使用聚合初始化的函数对象的方法?