struct X
{
X(X&); // (1)
X(X&&); // (2)
X(const X&); // (3)
X(const X&&); // (4)
};
是否有任何情况会在重载决议中选择(4)
?
答案 0 :(得分:9)
是。一种情况是当你有一个const
返回值的函数时:
const X f();
X x(f());
答案 1 :(得分:2)
另一种情况是当您将std::move
应用于const
对象时,如下例所示:
#include <iostream>
using namespace std;
struct X
{
X() { cout << "default" << endl; }
X(X&) { cout << "non const copy" << endl; } // (1)
X(X&&) { cout << "non const move" << endl; } // (2)
X(const X&) { cout << "const copy" << endl; } // (3)
X(const X&&){ cout << "const move" << endl; } // (4)
};
void f(X const x)
{
}
int main()
{
X const x;
f(std::move(x));
return 0;
}
上一个答案(X const f()
)中提到的情况可能不太常见,因为在执行RVO时,编译器大部分时间都忽略了移动构造函数(即使构造函数有侧面,也可以这样做 - 效果)。
将const
对象移动到另一个const
对象作为逻辑操作确实有意义,如果您没有定义const
移动构造函数,那么您将不被允许这样做。移动只是转移所有权,所以在我看来,作为一种逻辑操作,它应该得到支持。
虽然确实从高级别的角度来看你不应该修改const
对象并确实移动一个对象需要修改它(在大多数情况下),但是有一些众所周知的类似情况。可以在幕后修改const
对象,以实现更高级别的概念操作。考虑一个需要锁定非const成员互斥锁的const
成员函数的例子:你可以将互斥变量声明为mutable
,将其视为非const对象。
因此,即使在这种情况下,我将其视为const
移动构造函数中的合法操作(只要需要)来修改移动对象的mutable
成员(可能是一些布尔标记到由对象的析构函数检查)。请注意,如果从上面的代码中删除const
构造函数(3)和(4),那么它将无法编译。如果仅删除(4),则将选择复制构造函数(3) - 这意味着您将无法移动const
对象。