我试图从“ Effective Modern C ++”中了解关于特殊成员函数生成的第17项,因此我尝试了一些示例并试图对某些行为进行推理。书中写着:
..当我引用移动操作移动或构造数据成员或基类的移动操作时,并不能保证实际上会发生移动。实际上,“成员移动”更像是成员移动请求,因为未启用移动的类型(即,不提供对移动操作的特殊支持,例如,大多数C ++ 98旧类) ”通过他们的复制操作。 ... 此外,不会为任何明确声明复制操作的类生成移动操作。
如果我显式删除move构造函数,则下面的代码会出错,但是如果我不删除对象“ s1”,则将其复制而没有任何错误。这是指向相同代码的wandbox链接:wandbox link。我想我不了解删除move构造函数与不定义一个构造函数之间的区别。
#include <iostream>
struct S
{
S() = default;
S(const S&) {
std::cout << "Copying" << std::endl;
}
// S(S&&) = delete;
};
S return_lvalue() {
S ret{};
return ret;
}
int main() {
std::cout << "Hello world" << std::endl;
// Error here if I delete move constructor
S s1 = return_lvalue();
}
答案 0 :(得分:3)
我想我不了解删除move构造函数和不定义一个构造函数之间的区别。
完成时
struct S
{
S() = default;
S(const S&) {
std::cout << "Copying" << std::endl;
}
};
编译器将不会生成move构造函数。如果您尝试移动它,则过载解析将仅找到S(const S&)
,并且您将获得一个副本。使用
struct S
{
S() = default;
S(const S&) {
std::cout << "Copying" << std::endl;
}
S(S&&) = delete;
};
当您移动类型为S
的对象时,重载分辨率会找到S(const S&)
和S(S&&)
,但会选择S(S&&)
,因为这是更好的匹配。然后看到它已被删除,并且出现错误。
您需要记住的是删除的构造函数,请不要从类中删除它们。它声明它们并使它们可用于重载解决方案,并且只有在发生重载解决方案之后,它才会检查是否将其删除。
答案 1 :(得分:0)
删除特殊成员函数与不声明它是不同的。等同于在使用它时声明它并强制编译错误。
这样,删除移动ctor并不会带来很多好处……除非您由于某种原因也删除了复制ctor,但是根本就不用声明移动ctor。
这与报价没有多大关系,也就是说,如果您要做声明了一个举动但没有做任何“搬迁”,那么最终实际上没有任何价值感动,可能与用户的期望相反。
我建议您不要声明移动ctor。同样,这与被删除不一样。而且不会自动生成一个,因为您有一个副本ctor。
在此处查找更多技术信息:
请注意,由于省略,您的程序在C ++ 17模式下都可以编译。