聚合初始化不支持构造函数访问[重复]

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;,在上述过程中根本不会考虑默认构造函数,那么声明为deleteprivate的事实就无关紧要了。

顺便说一句:对于DefaultPrivate x; default initialization 执行,

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

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

如果你使用聚合初始化,比如DefaultPrivate x;,代码也可以正常工作;而n_ 将是value initialized(然后是zero initialized)作为0

LIVE

【讨论】:

是的,类型是聚合的,但它是私人意义上的聚合,或者我希望是这样,否则我不会在标题中使用聚合 @WernerErasmus 答案已修改。关键是这种情况下不会考虑构造函数,所以没关系。

以上是关于聚合初始化不支持构造函数访问[重复]的主要内容,如果未能解决你的问题,请参考以下文章

具有聚合初始化的 C++11 构造函数委托

Boost(或其他库)是不是提供了一种将“无构造函数”类的名称提升为使用聚合初始化的函数对象的方法?

P1008(“禁止与用户声明的构造函数聚合”)在实践中何时有用?

如何使用构造函数初始化数组? C++ [重复]

在构造函数中调用类成员的构造函数

为啥统一初始化没有显式构造函数[重复]