在C++11中,标准库在<utility>中提供了一个有用的函数std::move,std::move并不能移动任何东西,它唯一的功能是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义。从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue);
//摘自https://zh.cppreference.com/w/cpp/utility/move #include <iostream> #include <utility> #include <vector> #include <string> int main() { std::string str = "Hello"; std::vector<std::string> v; //调用常规的拷贝构造函数,新建字符数组,拷贝数据 v.push_back(str); std::cout << "After copy, str is \"" << str << "\"\n"; //调用移动构造函数,掏空str,掏空后,最好不要使用str v.push_back(std::move(str)); std::cout << "After move, str is \"" << str << "\"\n"; std::cout << "The contents of the vector are \"" << v[0] << "\", \"" << v[1] << "\"\n"; }
输出:
After copy, str is "Hello" After move, str is "" The contents of the vector are "Hello", "Hello"
std::move是一个用于提示优化的函数,过去的c++98中,由于无法将作为右值的临时变量从左值当中区别出来,所以程序运行时有大量临时变量白白的创建后又立刻销毁,其中又尤其是返回字符串std::string的函数存在最大的浪费。
比如:
1 std::string fileContent = “oldContent”; 2 s = readFileContent(fileName);
因为并不是所有情况下,C++编译器都能进行返回值优化,所以,向上面的例子中,往往会创建多个字符串。readFileContent如果没有内 部状态,那么,它的返回值多半是std::string(const std::string的做法不再被推荐了),而不是const std::string&。这是一个浪费,函数的返回值被拷贝到s中后,栈上的临时对象就被销毁了。
在C++11中,编码者可以主动提示编译器,readFileContent返回的对象是临时的,可以被挪作他用:std::move。
将上面的例子改成:
1 std::string fileContent = “oldContent”; 2 s = std::move(readFileContent(fileName));
后,对象s在被赋值的时候,方法std::string::operator =(std::string&&)会被调用,符号&&告诉std::string类的编写者,传入的参数是一个临时对 象,可以挪用其数据,于是std::string::operator =(std::string&&)的实现代码中,会置空形参,同时将原本保存在中形参中的数据移动到自身。
不光是临时变量,只要是你认为不再需要的数据,都可以考虑用std::move移动。
比较有名的std::move用法是在swap中:
1 template<typename T> 2 void swap(T& a, T& b) 3 { 4 T t(std::move(a)); // a为空,t占有a的初始数据 5 a = std::move(b); // b为空, a占有b的初始数据 6 b = std::move(t); // t为空,b占有a的初始数据 7 }
总之,std::move是为性能而生的,正式因为了有了这个主动报告废弃物的设施,所以C++11中的STL性能大幅提升,即使C++用户仍然按找旧有的方式来编码,仍然能因中新版STL等标准库的强化中收益。
https://blog.csdn.net/p942005405/article/details/84644069
https://www.cnblogs.com/keepsimple/p/3250245.html