显式默认的move构造函数使该结构不可复制

时间:2019-08-24 15:20:25

标签: c++ constructor default move

当我在Visual Studio 2019中声明这样的基本结构时:

struct Test
{
    Test(Test &&test) = default;
};

以下断言失败:

static_assert(std::is_trivially_copyable<Test>::value, "Test is not trivially copyable !");

这个:

struct Test
{
    Test(const Test &test) = default;
};

或这个:

struct Test
{

};

显然可以。但是我真的不明白第一个发生了什么。就复制行为而言,这与其他之间有何区别?

1 个答案:

答案 0 :(得分:2)

这是Visual Studio中现代版本C ++的错误,但从技术上讲,它不是原始版本C ++ 11的错误。

首先,当我提到Test时,是在谈论您的第一个定义。这样我们就很清楚了。

除非显式指定,否则通过显式默认Test的move构造函数,将导致编译器隐式delete 复制构造函数和赋值运算符。该规则背后的思想是,如果您竭尽全力明确地default构造函数,那么您可能正试图用这种说法。

仅具有默认移动构造函数的类型看起来类似于仅移动类型,因此标准假定这就是您想要的。而且,如果您不想这样做,则需要将其拼写清楚。

复制构造函数不会发生这种情况,因为移动被认为是复制的一种特殊形式。如果类型是默认可复制的,则它在逻辑上是默认可移动的,因此将move构造函数隐式保留为默认是有意义的。

这样的事情就是为什么您不应该default使用特殊的成员函数,除非您不知道这会如何影响其他成员或者您打算default/delete /实现所有其他成员函数。

在C ++ 11的初始版本中,默认移动构造函数的复制隐式删除将使Test不可TriviallyCopyable。但是,琐碎可复制性的措词在C ++ 14 via a defect report周围已更改。即使删除了某些复制/移动构造函数/赋值运算符,新的措辞也允许类型是TriviallyCopyable。因此,使Test是TriviallyCopyable的。缺陷修复程序通常是追溯性应用的,因此从技术上讲,现代的C ++ 11实现也应该起作用。

Visual Studio从未更改以适应新的措辞。因此是错误。