如果在C ++ 17中“删除”或“未声明”移动/复制构造函数/赋值,是否已经建立?

Adr*_*ian 9 c++ language-lawyer c++17

我一直在寻找有关自动生成移动操作的规则的答案,并希望答案现在已经确定。

基于类中已声明的内容的幻灯片显示了“未声明”,“默认”或“已删除”哪些构造函数/赋值运算符:

在此处输入图片说明

这是从这些幻灯片中获取的,红色方块表示不赞成使用此行为。

编译以下内容时:

#include <iostream>
struct X
{
  template<typename...T>
  X(T&&...) {
    std::cout << "Yay!\n";
  }

  ~X() {}
};

int main() {
  X x0;
  X x1{x0};
  X x2{std::move(x0)};
}
Run Code Online (Sandbox Code Playgroud)

看起来它们已经被“未声明”了,因为它已编译并且输出为“是!”。三遍(至少对我来说这是件好事)。但是我想确认我可以依靠这种行为。

编辑

据指出,通过坦率的说,如果一个拷贝构造函数也被添加,还在说“耶!” 三遍,这是有趣的行为。做进一步的测试,如果添加了move构造函数,它只会说“是!”。两次。谁能解释这种行为?

Oli*_*liv 2

根据 N4659(几乎是 C++17 标准),它们仍然被定义为默认值,但该行为(仍然)已被弃用。

如果类定义没有显式声明复制构造函数,则隐式声明非显式复制构造函数。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除;否则,它被定义为默认值。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。

如果类定义没有显式声明复制赋值运算符,则隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制赋值运算符被定义为已删除;否则,它被定义为默认值。如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。