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

Bor*_*rja 11 c++ struct class c++11 visual-c++-2015

我在这个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;
};
Run Code Online (Sandbox Code Playgroud)

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

错误C2280:'std :: condition_variable :: condition_variable(const std :: condition_variable&)':尝试引用已删除的函数1> c:\ program files(x86)\ microsoft visual studio 14.0\vc\include\mutex(550 ):注意:请参阅'std :: condition_variable :: condition_variable'的声明.

如果我更改Test constructor为不使用C++ 11统一初始化Struct它编译好了.

Test() : 
        myClass{},
        myStruct() // <--- CHANGE
    {};
Run Code Online (Sandbox Code Playgroud)

我没有得到为什么Struct类型使用复制构造函数,但Class似乎没问题.只有Struct拥有不可复制的成员才会发生这种情况.

我还注意到,如果我初始化成员初始化列表的Struct外部Test Class它工作:

int main()
{
    NonCopiableStruct a{};   
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

不知道为什么这段代码失败了?引擎盖下发生了什么?myClass初始化和myStruct初始化有什么区别?为什么如果在类成员上使用它将不会编译initializer list但是我可以在外面使用它吗?我试过了GCC,似乎没问题.

Sto*_*ica 14

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

类版本是初始化的值{}.struct版本是聚合初始化的.一个符合编译器应该只列出初始化condition_{},因为你没有为它提供一个初始化.

但是,MSVC似乎对于聚合的成员是从初始化列表中的相应初始化器初始化的事实感到磕磕绊绊.它似乎检查复制c'tor,即使它不应该实际使用它.

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