考虑this代码:
#include <iostream>
#include <string>
using namespace std;
class Movable {
public:
Movable(const string& name) : m_name(name) { }
Movable(const Movable& rhs) {
cout << "Copy constructed from " << rhs.m_name << endl;
}
Movable(Movable&& rhs) {
cout << "Move constructed from " << rhs.m_name << endl;
}
Movable& operator = (const Movable& rhs) {
cout << "Copy assigned from " << rhs.m_name << endl;
}
Movable& operator = (Movable&& rhs) {
cout << "Move assigned from " << rhs.m_name << endl;
}
private:
string m_name;
};
int main() {
Movable obj1("obj1");
Movable obj2(std::move(obj1));
obj2 = std::move(obj1); // For demostration only
const Movable cObj("cObj");
Movable tObj(std::move(cObj));
tObj = std::move(cObj); // For demonstration only
}
它的输出是:
Move constructed from obj1
Move assigned from obj1
Copy constructed from cObj
Copy assigned from cObj
如您所见,在这些行中,
Movable tObj(std::move(cObj));
tObj = std::move(cObj); // For demonstration only
我打算将cObj
移到tObj
(使用赋值运算符的第二步仅用于演示)。但是,正如您在输出中看到的那样,cObj
仅已复制到tObj
。
上面的例子只是一个演示,我不知道这有什么实际用途。但我会问:
const
对象吗? 其他:我忘了问。如果我可以移动const
对象,我应该如何? (const_cast
?)
答案 0 :(得分:2)
当然,只要对象的非mutable
状态不会因为被移动而改变。
也许您有一个对应于文件内容或数据库记录的对象。它在mutable
成员中访问时会缓存数据。现在,您可以通过窃取其缓存数据来移动该对象,而无需实际修改对象。因此,对于该对象来说,移动构造函数和移动赋值运算符需要const Record&&
,这是有道理的(只要对象可以移动是有道理的)。
这是完全合法的,C ++ 11标准的第12.8p3节规定:
类
X
的非模板构造函数是移动构造函数,如果其第一个参数的类型为X&&
,const X&&
,volatile X&&
,或const volatile X&&
,并且没有其他参数,或者所有其他参数都有默认参数。
和p19:
用户声明的移动赋值运算符
X::operator=
是类X
的非静态非模板成员函数,其中只有一个X&&
类型的参数, {{1 }} ,const X&&
或volatile X&&
。
通过这种方式,你可以移动一个const volatile X&&
对象,const
新的 copy 无论你调用一个实例创建的移动,因此将缓冲区空间重新用于其他内容并避免新的分配,同时保留旧对象并准备好返回其内容(通过再次访问磁盘或数据库)(如果需要)。
答案 1 :(得分:2)
在代码中调用复制构造函数,因为move-constructor需要非const参数(Movable&&
),而参数是const对象(std::move(cObj)
的类型为const Movable&&
})。由于非const rvalue-reference无法绑定const rvalue,因此该重载将被丢弃,下一个最佳匹配是复制构造函数。
现在接下来的问题是,是否/何时可以移出const
对象。虽然从技术上讲你可以实现一个带const &&
的移动构造函数,你甚至可以在不调用未定义行为的情况下执行此操作(只是不修改源对象的任何非可变成员)问题是它是否有意义。我不认为它。
移动构造函数的存在通常表明存在由对象维护的资源,当不再需要源对象时,该资源可以有效地传输到另一个对象(例如,构造对象时)暂时的)。移动固有地修改源对象。不修改源对象的移动构造函数不能将资源从源对象移动到目标对象,它几乎没有任何意义。