详解C++移动语义std::move()
?
目錄
1. C++move的概念
2. C++move的特點
3. 左值、右值與左值引用、右值引用
3.1 左值和右值的概念
3.2 左值引用和右值引用
4. std::move詳解
4.1 std::move簡介
4.2 std::move詳解
4.3 std::move實現:
4.4 std::move的優點
4.5??std::move的使用
參考:
https://blog.csdn.net/s11show_163/article/details/114296006
https://blog.csdn.net/daaikuaichuan/article/details/88371948
https://zhuanlan.zhihu.com/p/94588204
https://www.cnblogs.com/SZxiaochun/p/8017475.html
https://www.cnblogs.com/yoyo-sincerely/p/8658075.html
左值引用與右值引用,以及為什么右值引用本身是左值的問題詳見:https://www.cnblogs.com/char-cheng/p/11026936.html
1. C++move的概念
一句話概括std::move ———— std::move是將對象的狀態或者所有權從一個對象轉移到另一個對象,只是轉移,沒有內存的搬遷或者內存拷貝。
2. C++move的特點
3. 左值、右值與左值引用、右值引用
右值引用(及其支持的Move語意和完美轉發)是C++0x加入的最重大語言特性之一。從實踐角度講,它能夠完美解決C++中長久以來為人所詬病的臨時對象效率問題。從語言本身講,它健全了C++中的引用類型在左值右值方面的缺陷。從庫設計者的角度講,它給庫設計者又帶來了一把利器。從庫使用者的角度講,不動一兵一卒便可以獲得“免費的”效率提升。
3.1 左值和右值的概念
3.2 左值引用和右值引用
引用是C++語法做的優化,引用的本質還是靠指針來實現的。引用相當于變量的別名。引用可以改變指針的指向,還可以改變指針所指向的值。
左值引用:type &引用名 = 左值表達式;就是對左值的引用 就是給左值取別名
右值引用:type &&引用名 = 右值表達式;就是對右值的引用 就是給右值取別名
int a=10; //a 是左值 double b=1.3; //b 是左值 //左值引用 int & Ta=a; //引用左值 故 是一個左值引用 double & Tb=b; //引用左值 故是一個左值引用再比如:
int a = 100; int&& b = 100;//右值引用 int& c = b; //正確,b為左值 int& d = 100; //錯誤4. std::move詳解
4.1 std::move簡介
在C++11中,標準庫在中提供了一個有用的函數std::move,std::move并不能移動任何東西,它唯一的功能是將一個左值引用強制轉化為右值引用,繼而可以通過右值引用使用該值,以用于移動語義。從實現上講,std::move基本等同于一個類型轉換:static_cast<T&&>(lvalue);
#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輸出為"Hello"//調用移動構造函數,掏空str,掏空后,最好不要使用strv.push_back(std::move(str));std::cout << "After move, str is \"" << str << "\"\n"; //str輸出為空std::cout << "The contents of the vector are \"" << v[0]<< "\", \"" << v[1] << "\"\n";//v[0]、v[1]都為"Hello" }輸出
After copy, str is "Hello" After move, str is "" The contents of the vector are "Hello", "Hello"
4.2 std::move詳解
std::move 的函數原型定義:
template <typename T> typename remove_reference<T>::type&& move(T&& t) {return static_cast<typename remove_reference<T>::type &&>(t); }首先,函數參數T&&是一個指向模板類型參數的右值引用,通過引用折疊,此參數可以與任何類型的實參匹配(可以傳遞左值或右值,這是std::move主要使用的兩種場景)。關于引用折疊如下:
所有右值引用折疊到右值引用上仍然是一個右值引用。(A&& && 變成 A&&) 。
所有的其他引用類型之間的折疊都將變成左值引用。 (A& & 變成 A&; A& && 變成 A&; A&& & 變成 A&)。
簡單來說,右值經過T&&傳遞類型保持不變還是右值,而左值經過T&&變為普通的左值引用。
//原始的,最通用的版本 template <typename T> struct remove_reference{typedef T type; //定義T的類型別名為type };//部分版本特例化,將用于左值引用和右值引用 template <class T> struct remove_reference<T&> //左值引用 { typedef T type; }template <class T> struct remove_reference<T&&> //右值引用 { typedef T type; } //舉例如下,下列定義的a、b、c三個變量都是int類型 int i; remove_refrence<decltype(42)>::type a; //使用原版本, remove_refrence<decltype(i)>::type b; //左值引用特例版本 remove_refrence<decltype(std::move(i))>::type b; //右值引用特例版本4.3 std::move實現:
1. 首先,通過右值引用傳遞模板實現,利用引用折疊原理將右值經過T&&傳遞類型保持不變還是右值,而左值經過T&&變為普通的左值引用,以保證模板可以傳遞任意實參,且保持類型不變。(cpr:先能夠把參數類型全都接收)
2. 然后我們通過static_cast<>進行強制類型轉換返回T&&右值引用,而static_cast之所以能使用類型轉換,是通過remove_refrence::type模板移除T&&,T&的引用,獲取具體類型T(模板偏特化)。(cpr:再把接收的參數的原引用抹除強轉成右引)
4.4 std::move的優點
std::move語句可以將左值變為右值而避免拷貝構造。
std::move是將對象的狀態或者所有權從一個對象轉移到另一個對象,只是轉移,沒有內存的搬遷或者內存拷貝。
4.5??std::move的使用
比如向vector中插入新元素。
int a = 1; vector<int> vec; vec.push_back(move(a));總結
以上是生活随笔為你收集整理的详解C++移动语义std::move()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: thinkpad卡在logo界面_四大系
- 下一篇: BATJ原来是这样玩大数据的!