C++中的std::move

在右值引用的文章中,我们知道,借助右值引用可以为指定类添加移动构造函数,这样当使用该类的右值对象(可以理解为临时对象)初始化同类对象时,编译器会优先选择移动构造函数。

注意,移动构造函数的调用时机是:用同类的右值对象初始化新对象。那么,用当前类的左值对象(有名称,能获取其存储地址的实例对象)初始化同类对象时,是否就无法调用移动构造函数了呢?当然不是,C++11标准中已经给出了解决方案,即调用move()函数。

move虽然本意为”移动”,但该函数并不能移动任何数据,它的功能很简单,就是将某个左值强制转化为右值,继而可以通过右值引用使用该值,以用于移动语义。

举一个例子,C++标准库中向量vector的push_back操作,会对参数的对象进行复制,连数据也会复制。这就会造成对象内存的额外创建, 本来原意是想把参数push_back进去就行了,通过std::move,就可以避免不必要的拷贝操作。

std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝所以可以提高利用效率,改善性能。

move的本质就是帮助编译器选择重载函数, 告诉编译器”请尽量把此参数当做右值来处理”,并且告诉编译器,之后将不再使用这个对象。因为使用拷贝构造方法的话,是对原来的对象没有任何影响的,但是如果使用的是移动构造方法,由于只是发生了所有权转移,并没有复制该对象,因此使用移动构造方法后,原来的对象将无法使用。

1
2
3
4
5
6
7
8
std::string str = "Hello";
std::vector<std::string> v;
v.push_back(std); // 调用复制构造方法,对str无影响
std::cout << str; // "Hello"
v.push_back(std::move(str)); // 调用移动构造方法,之后str无法继续使用
std::cout << str; // "",str此时为空
v.push_back(std::move(str)); // 可以执行,但是新元素是空
std::cout << v.size(); // 3,"Hello"->"Hello"->""

C++中的std::move
http://nougatca.github.io/2023/01/03/cpp-std-move/
作者
Changan NIU
发布于
2023年1月3日
许可协议