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


我在这个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失败,并显示以下错误:

错误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
    {};

我不明白为什么 Struct type使用复制构造函数但是 Class 好像。它只发生在 Struct 拥有不可复制的成员。

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

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

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


8978
2018-01-11 07:46


起源

您根本不需要初始化它们。
切换到VS2017。


答案:


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

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

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

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


14
2018-01-11 07:52