c++ - 如果在 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)};
}
看起来它们已经“未声明”,因为它编译并且输出是“Yay!” 三倍(这很好,至少对我来说)。但我想确认我可以依赖这种行为。
编辑
Frank已经指出,如果还添加了复制构造函数,它仍然会说“耶!” 三次,这是有趣的行为。做进一步的测试,如果添加了移动构造函数,它只会说“耶!” 两次。谁能解释这种行为?
解决方案
根据 N4659(几乎是 C++17 标准),它们仍被定义为默认值,但行为(仍然)被弃用。
- 对于复制构造函数,请参见[class.copy.ctor]/6:
如果类定义没有显式声明复制构造函数,则隐式声明非显式构造函数。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数定义为已删除;否则,它被定义为默认值。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。
- 有关复制分配,请参阅[class.copy.assign]/2:
如果类定义没有显式声明复制赋值运算符,则隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制赋值运算符被定义为删除;否则,它被定义为默认值。如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。
推荐阅读
- javascript - 将导航栏 LOGIN 更改为 LOGOUT
- php - 无法在 PHP 中检测到任何有意义的时间差异(恒定时间攻击)
- bluetooth-lowenergy - 使用 Gattlib 包写入而不响应 BLE 设备-RN4871
- mule-studio - 从 mulesoft 调用 oracle 包
- teradata - 修剪雪花中的列数据
- java - 为什么我得到 DocumentBuilder 解析异常?
- php - 如何在 Symfony 中从 Sentry 中排除异常?
- javascript - 如何使用单槽修改数据表中的任何列
- java - 如何将地图列表转换为哈希数组
- javascript - 在使用 flex-grids 时,有没有办法解决在 slideToggle() 内的 slideToggle() 内的 slideToggle() 问题?