成员初始化列表错误的统一初始化

Uniform initialization on member initializer list error

我在此 C++11 代码上遇到编译错误,但我不知道为什么。这是代码:

#include <condition_variable>

class NonCopiableClass
{
    std::condition_variable condition_;
};

struct NonCopiableStruct
{
    std::condition_variable condition_;
};

class Test
{
 public:
    Test() : 
        myClass{},
        myStruct{}
    {};
 private:
    NonCopiableClass myClass;
    NonCopiableStruct myStruct;
};

Visual Studio 2015 失败并出现以下错误:

error C2280: 'std::condition_variable::condition_variable(const std::condition_variable &)': attempting to reference a deleted function 1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\mutex(550): note: see declaration of 'std::condition_variable::condition_variable'.

如果我将 Test constructor 更改为不使用 Struct 的 C++11 统一初始化,它可以编译。

Test() : 
        myClass{},
        myStruct() // <--- CHANGE
    {};

我不明白为什么 Struct 类型使用复制构造函数,但 Class 似乎没问题。它只发生在 Struct 具有不可复制的成员时。

我还注意到,如果我在 Test Class 成员初始化列表之外初始化 Struct 它会起作用:

int main()
{
    NonCopiableStruct a{};   
    return 0;
}

知道为什么这段代码会失败吗?。幕后发生了什么? myClass初始化和myStruct初始化有什么区别?为什么在 class 成员 initializer list 上使用它不会编译,但我可以在外面使用它吗?我试过GCC,好像没问题。

这似乎是一个 MSVC 错误。不同之处在于 struct 版本是聚合,而 class 版本不是(由于默认的私有访问说明符)。

class版本是由{}初始化的值。结构版本是聚合初始化的。符合标准的编译器应该只列出初始化 condition_{},因为您没有为它提供初始化程序。

但是 MSVC 似乎对聚合的成员是从初始化程序列表中的相应初始化程序进行复制初始化这一事实感到困惑。它似乎在检查复制 c'tor,即使它实际上不应该使用它。

当相同类型的对象在成员初始化器列表之外 初始化时,它知道该做什么这一事实进一步支持了这一点。