c++11中std::move函數(shù)的使用
C++11在運行期有所增強,通過增加核心的右值引用機制來改善臨時對象導致的效率低下的問題。C++臨時對象引入了多余的構(gòu)造、析構(gòu)及其內(nèi)部資源的申請釋放函數(shù)調(diào)用,導致程序運行時性能受損,這一點被廣為詬病。C++標準委員會在C++11中引入了右值引用這個核心語言機制,來提升運行期性能
過std::move,可以避免不必要的拷貝操作。
std::move是為性能而生。
std::move是將對象的狀態(tài)或者所有權(quán)從一個對象轉(zhuǎn)移到另一個對象,只是轉(zhuǎn)移,沒有內(nèi)存的搬遷或者內(nèi)存拷貝。
變量表達式是一個左值,即使這個變量是一個右值引用類型,也是將其看成是左值的。
于是有:變量是一個左值,我們不能將一個右值引用直接綁定到一個變量上,即使這個變量是右值引用類型也不行。
但是。我們可以顯式的將一個左值轉(zhuǎn)換為對應的右值引用類型。另外,可以通過move庫函數(shù)來獲得綁定到左值上的右值引用。此函數(shù)定義在utility中。
如:
int &&rr1 = 42; //正確,字面值常量是右值 int &&rr2 = rr1; //錯誤,表達式rr1是左值 int &&rr3 = std::move(rr1); //正確
move告訴編譯器我們有一個左值,但我們希望像一個右值一樣處理它。注意:調(diào)用move意味著承諾:除了對rr1賦值和銷毀它以外,我們不再使用它。在調(diào)用move之后,我們不能對移后源對象的值做任何假設。
(我們可以銷毀一個移后源對象,也可以賦予它新值,但是不能使用一個移后源對象的值。)
我們對move不提供using聲明,我們直接調(diào)用std::move而不是move。原因是:如果在應用程序中定義一個標準庫中已有的名字,則將出現(xiàn)一下兩種可能中的一種:
(1)要么根據(jù)一般的重載規(guī)則確定某次調(diào)用應該執(zhí)行函數(shù)的哪個版本,
(2)要么應用程序根本就不會執(zhí)行函數(shù)的標準庫版本。
因此,對于move的名字沖突相比其他標準庫函數(shù)的沖突頻繁的多。于是我們在調(diào)用move函數(shù)時,是使用std::move而不是move。
原型定義中的原理實現(xiàn):
首先,函數(shù)參數(shù)T&&是一個指向模板類型參數(shù)的右值引用,通過引用折疊,此參數(shù)可以與任何類型的實參匹配(可以傳遞左值或右值,這是std::move主要使用的兩種場景)。關(guān)于引用折疊如下:
公式一)X& &、X&& &、X& &&都折疊成X&,用于處理左值
?
string s("hello");
std::move(s) => std::move(string& &&) => 折疊后 std::move(string& )
此時:T的類型為string&
typename remove_reference<T>::type為string?
整個std::move被實例化如下
string&& move(string& t) //t為左值,移動后不能在使用t
{
? ? //通過static_cast將string&強制轉(zhuǎn)換為string&&
? ? return static_cast<string&&>(t);?
}
?公式二)X&& &&折疊成X&&,用于處理右值
std::move(string("hello")) => std::move(string&&)
//此時:T的類型為string?
// ? ? remove_reference<T>::type為string?
//整個std::move被實例如下
string&& move(string&& t) //t為右值
{
? ? return static_cast<string&&>(t); ?//返回一個右值引用
}簡單來說,右值經(jīng)過T&&傳遞類型保持不變還是右值,而左值經(jīng)過T&&變?yōu)槠胀ǖ淖笾狄?
②對于static_cast<>的使用注意:任何具有明確定義的類型轉(zhuǎn)換,只要不包含底層const,都可以使用static_cast。
double d = 1; void* p = &d; double *dp = static_cast<double*> p; //正確 ? const char *cp = "hello"; char *q = static_cast<char*>(cp); //錯誤:static不能去掉const性質(zhì) static_cast<string>(cp); //正確?
③對于remove_reference是通過類模板的部分特例化進行實現(xiàn)的,其實現(xiàn)代碼如下
//原始的,最通用的版本
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; ?//右值引用特例版本?總結(jié):
std::move實現(xiàn),首先,通過右值引用傳遞模板實現(xiàn),利用引用折疊原理將右值經(jīng)過T&&傳遞類型保持不變還是右值,而左值經(jīng)過T&&變?yōu)槠胀ǖ淖笾狄?,以保證模板可以傳遞任意實參,且保持類型不變。然后我們通過static_cast<>進行強制類型轉(zhuǎn)換返回T&&右值引用,而static_cast<T>之所以能使用類型轉(zhuǎn)換,是通過remove_refrence<T>::type模板移除T&&,T&的引用,獲取具體類型T。
到此這篇關(guān)于c++11中std::move函數(shù)的使用的文章就介紹到這了,更多相關(guān)c++11 std::move函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)LeetCode(154.尋找旋轉(zhuǎn)有序數(shù)組的最小值之二)
這篇文章主要介紹了C++實現(xiàn)LeetCode(154.尋找旋轉(zhuǎn)有序數(shù)組的最小值之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
C++高級數(shù)據(jù)結(jié)構(gòu)之優(yōu)先隊列
這篇文章主要介紹了C++高級數(shù)據(jù)結(jié)構(gòu)之優(yōu)先隊列,文章圍繞主題的相關(guān)資料展開詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-05-05
C++實現(xiàn)一個線程安全的單例工廠實現(xiàn)代碼
這篇文章主要介紹了 C++實現(xiàn)一個線程安全的單例工廠實現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05
Visual?Studio配置靜態(tài)庫詳細步驟和關(guān)鍵配置項
這篇文章主要介紹了Visual?Studio配置靜態(tài)庫的詳細步驟和關(guān)鍵配置項的相關(guān)資料,靜態(tài)庫是一系列預先編譯好的目標文件(.o文件或.obj文件)的集合,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-12-12

