成员初始化列表错误

时间:2018-01-11 07:46:43

标签: c++ class c++11 struct 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;
};

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

  

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

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:14)

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

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

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

当成员初始化列表 之外,它知道如何处理相同类型的对象时,会进一步支持这一点。