【问题标题】: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 result{10};
    return result;
}

int main() {
    DefaultPrivate x; //Fails
    DefaultPrivate y{10};//Works
    return 0;
}

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

GCC 6.3 和 VCC 2017 都是这种情况

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

【问题讨论】:

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


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

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

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

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

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

    LIVE

    【讨论】:

    • 是的,类型是聚合的,但它是私人意义上的聚合,或者我希望是这样,否则我不会在标题中使用聚合
    • @WernerErasmus 答案已修改。关键是这种情况下不会考虑构造函数,所以没关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2018-08-02
    • 2016-10-02
    相关资源
    最近更新 更多