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

11

我在这段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 &)': 尝试引用已删除的函数 1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\mutex(550): 参见“std::condition_variable::condition_variable”的声明。
如果我更改 Test constructor 以不使用C++11 uniform initialization,则可以编译通过。
Test() : 
        myClass{},
        myStruct() // <--- CHANGE
    {};

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

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

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

有什么想法,为什么这段代码失败了?发生了什么?myClass 的初始化和 myStruct 的初始化有什么区别?如果在类成员的 initializer list 中使用它,为什么无法编译,但在外部使用是可以的?我已经在 GCC 上尝试过,似乎没问题。


你根本不需要初始化它们。 - user2672107
1
切换到VS2017。 - user2672107
1个回答

14

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

class版本通过{}进行值初始化。struct版本是聚合体初始化。一个符合规范的编译器应该只用{}列出初始化列表中的condition_,因为你没有为它提供初始化程序。

但是,MSVC似乎在处理聚合体成员时遇到了问题,由对应的初始化器列表中的初始化器进行复制初始化。即使它并不打算实际使用它,它似乎也要检查复制构造函数。

这也得到了支持,因为当同一类型的对象在成员初始化列表之外初始化时,它知道该怎么做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接