溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何進(jìn)行c++11中std::move函數(shù)的使用

發(fā)布時(shí)間:2022-01-27 09:06:44 來(lái)源:億速云 閱讀:178 作者:柒染 欄目:開(kāi)發(fā)技術(shù)

這篇文章給大家介紹如何進(jìn)行c++11中std::move函數(shù)的使用,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

C++11在運(yùn)行期有所增強(qiáng),通過(guò)增加核心的右值引用機(jī)制來(lái)改善臨時(shí)對(duì)象導(dǎo)致的效率低下的問(wèn)題。C++臨時(shí)對(duì)象引入了多余的構(gòu)造、析構(gòu)及其內(nèi)部資源的申請(qǐng)釋放函數(shù)調(diào)用,導(dǎo)致程序運(yùn)行時(shí)性能受損,這一點(diǎn)被廣為詬病。C++標(biāo)準(zhǔn)委員會(huì)在C++11中引入了右值引用這個(gè)核心語(yǔ)言機(jī)制,來(lái)提升運(yùn)行期性能

過(guò)std::move,可以避免不必要的拷貝操作。

std::move是為性能而生。

std::move是將對(duì)象的狀態(tài)或者所有權(quán)從一個(gè)對(duì)象轉(zhuǎn)移到另一個(gè)對(duì)象,只是轉(zhuǎn)移,沒(méi)有內(nèi)存的搬遷或者內(nèi)存拷貝。

變量表達(dá)式是一個(gè)左值,即使這個(gè)變量是一個(gè)右值引用類型,也是將其看成是左值的。

于是有:變量是一個(gè)左值,我們不能將一個(gè)右值引用直接綁定到一個(gè)變量上,即使這個(gè)變量是右值引用類型也不行。

但是。我們可以顯式的將一個(gè)左值轉(zhuǎn)換為對(duì)應(yīng)的右值引用類型。另外,可以通過(guò)move庫(kù)函數(shù)來(lái)獲得綁定到左值上的右值引用。此函數(shù)定義在utility中。

如:

int &&rr1 = 42;        //正確,字面值常量是右值
int &&rr2 = rr1;        //錯(cuò)誤,表達(dá)式rr1是左值
int &&rr3 = std::move(rr1);    //正確

move告訴編譯器我們有一個(gè)左值,但我們希望像一個(gè)右值一樣處理它。注意:調(diào)用move意味著承諾:除了對(duì)rr1賦值和銷毀它以外,我們不再使用它。在調(diào)用move之后,我們不能對(duì)移后源對(duì)象的值做任何假設(shè)。

(我們可以銷毀一個(gè)移后源對(duì)象,也可以賦予它新值,但是不能使用一個(gè)移后源對(duì)象的值。)

我們對(duì)move不提供using聲明,我們直接調(diào)用std::move而不是move。原因是:如果在應(yīng)用程序中定義一個(gè)標(biāo)準(zhǔn)庫(kù)中已有的名字,則將出現(xiàn)一下兩種可能中的一種:

(1)要么根據(jù)一般的重載規(guī)則確定某次調(diào)用應(yīng)該執(zhí)行函數(shù)的哪個(gè)版本,

(2)要么應(yīng)用程序根本就不會(huì)執(zhí)行函數(shù)的標(biāo)準(zhǔn)庫(kù)版本。

因此,對(duì)于move的名字沖突相比其他標(biāo)準(zhǔn)庫(kù)函數(shù)的沖突頻繁的多。于是我們?cè)谡{(diào)用move函數(shù)時(shí),是使用std::move而不是move。

原型定義中的原理實(shí)現(xiàn):

 首先,函數(shù)參數(shù)T&&是一個(gè)指向模板類型參數(shù)的右值引用,通過(guò)引用折疊,此參數(shù)可以與任何類型的實(shí)參匹配(可以傳遞左值或右值,這是std::move主要使用的兩種場(chǎng)景)。關(guān)于引用折疊如下:

      公式一)X& &、X&& &、X& &&都折疊成X&,用于處理左值

string s("hello");
std::move(s) => std::move(string& &&) => 折疊后 std::move(string& )
此時(shí):T的類型為string&
typename remove_reference<T>::type為string 
整個(gè)std::move被實(shí)例化如下
string&& move(string& t) //t為左值,移動(dòng)后不能在使用t
{
    //通過(guò)static_cast將string&強(qiáng)制轉(zhuǎn)換為string&&
    return static_cast<string&&>(t); 
}

      公式二)X&& &&折疊成X&&,用于處理右值

std::move(string("hello")) => std::move(string&&)
//此時(shí):T的類型為string 
//     remove_reference<T>::type為string 
//整個(gè)std::move被實(shí)例如下
string&& move(string&& t) //t為右值
{
    return static_cast<string&&>(t);  //返回一個(gè)右值引用
}

簡(jiǎn)單來(lái)說(shuō),右值經(jīng)過(guò)T&&傳遞類型保持不變還是右值,而左值經(jīng)過(guò)T&&變?yōu)槠胀ǖ淖笾狄?

②對(duì)于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); //錯(cuò)誤:static不能去掉const性質(zhì)
static_cast<string>(cp); //正確

③對(duì)于remove_reference是通過(guò)類模板的部分特例化進(jìn)行實(shí)現(xiàn)的,其實(shí)現(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三個(gè)變量都是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實(shí)現(xiàn),首先,通過(guò)右值引用傳遞模板實(shí)現(xiàn),利用引用折疊原理將右值經(jīng)過(guò)T&&傳遞類型保持不變還是右值,而左值經(jīng)過(guò)T&&變?yōu)槠胀ǖ淖笾狄?,以保證模板可以傳遞任意實(shí)參,且保持類型不變。然后我們通過(guò)static_cast<>進(jìn)行強(qiáng)制類型轉(zhuǎn)換返回T&&右值引用,而static_cast<T>之所以能使用類型轉(zhuǎn)換,是通過(guò)remove_refrence<T>::type模板移除T&&,T&的引用,獲取具體類型T。

關(guān)于如何進(jìn)行c++11中std::move函數(shù)的使用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI