C 11中的右值引用及move語義程式設計

2021-07-09 08:49:32 字數 2962 閱讀 1615

c++0x中加入了右值引用,和move函式。右值引用出現之前我們只能用const引用來關聯臨時物件(右值)(造孽的vs可以用非const引用關聯臨時物件,請忽略vs),所以我們不能修臨時物件的內容,右值引用的出現就讓我們可以取得臨時物件的控制權,終於可以修改臨時物件了!而且書上說配合move函式,可以大大提高現有c++的效率。那麼是怎樣提高它的效率的呢?看段**先!

#include #include 

#include

#include

intmain()

output:

after copy, str is

"hello

"after move, str

is""

the contents of the vector are

"hello

", "

hello

"

看完大概明白一點兒了,加上move之後,str物件裡面的內容被"移動"到新的物件中並插入到陣列之中了,同時str被清空了。這樣一來省去了物件拷貝的過程。所以說在str物件不再使用的情況下,這種做法的效率更高一些!但問題是str的內容在什麼地方被移走的呢?move函式到底是幹啥的?扣一下stl原始碼吧,下面是move模板的原始碼:

//

template function move

templateinline

typename tr1::_remove_reference

<_ty>::_type&&move(_ty

&&_arg)

好吧,看過了這段,可能有人又迷惑了,不是說有名左指變數不能繫結到右值引用上面麼?為什麼move函式的引數是右值引用卻可以接受左值變數作為引數?難道stl錯了麼?事實上,c++0x在引入右值引用的時候對函式模板自動推導也加入了新的規則,簡單的說,像例子中的這種情況,模板引數是_ty而函式的引數是_ty&&(右值引用),同時_arg是string的左值物件的情況下,會觸發乙個特殊規則,_ty會推導成string&,也就是說此事推導出來的函式與move一致。那麼move

(_ty

&&_arg) 得到的應該是move

(string& 

&&_arg)

這個時候根據引用摺疊原則,會變成這個樣子move

(string&

_arg)

。詳細的描述參見白雲飄飄翻譯的vc技術文件(函式的返回值嘛,就好說了,就是返回所持有型別的右值引用了。所以,move函式的作用很簡單,不管你給什麼引數,都返回對應型別的右值引用!那麼,上面例子中str的不是在move函式中被移走的。綜上,我們猜測str內容肯定是在構造新物件的過程中被新物件偷走的,也就是在string的引數為右值引用的建構函式中被偷走的!翻看string的原始碼(來自vs實現的stl

),果然如此啊!如下:

basic_string(_myt&&_right)

: _mybase(_std forward

<_alloc>(_right._alval))

_myt& assign(_myt&&_right)

this->_mysize =_right._mysize;

this->_myres =_right._myres;

_right._tidy();

}return (*this

); }

所以,我們知道了,c++0x在stl模板庫中加入了引數為右值引用的建構函式,用於把引數所關聯物件中的資料移動到新物件當中,避免了深度拷貝,增加了效率。再詳細翻看原始碼,可以發現除了建構函式,operator=也過載了乙個引數為右值引用的函式,用途和建構函式類似。所以我們自定義中的類也應該增加引數為右值引用的建構函式和過載賦值運算子!原因是啥,看例子!

未定義引數為右值引用的建構函式:

#include #include 

#include

#include

using

namespace

std;

class

mypoint

mypoint(

const mypoint&p)

:comment(p.comment),x(p.x),y(p.y)

{}//mypoint(mypoint

&&p)

// :comment(move(p.comment)), x(p.x), y(p.y)

//string

tostring()

string

comment;

intx;

inty;

};int

main()

結果:

after copy, str is

"first point: 9 7

"after move, str is"

first point: 9 7

"the contents of the vector are

"first point: 9 7

", "

first point: 9 7

"

定義了引數為右值引用的建構函式之後:

after copy, str is

"first point: 9 7

"after move, str is"

: 0 0

"the contents of the vector are

"first point: 9 7

", "

first point: 9 7

"

綜上所述,c++0x中的move語義程式設計,不僅僅是在應用的時候使用引數中加上move,對於自定義類需要增加引數為右值引用的建構函式和賦值運算子,這種建構函式我們稱為move建構函式!公司裡面的c++標準已經更新,要求在定義copy建構函式的同時定義move建構函式,雖然現在這種程式設計方法沒有流行,但是我相信以後這將成為另外乙個媲美引用的優化執行速度的程式設計方法,我們拭目以待!

C 11中的右值引用及move語義程式設計

c 0x中加入了右值引用,和move函式。右值引用出現之前我們只能用const引用來關聯臨時物件 右值 造孽的vs可以用非const引用關聯臨時物件,請忽略vs 所以我們不能修臨時物件的內容,右值引用的出現就讓我們可以取得臨時物件的控制權,終於可以修改臨時物件了!而且書上說配合move函式,可以大大...

C 11中的右值引用及move語義程式設計

c 0x中加入了右值引用,和move函式。右值引用出現之前我們只能用const引用來關聯臨時物件 右值 造孽的vs可以用非const引用關聯臨時物件,請忽略vs 所以我們不能修臨時物件的內容,右值引用的出現就讓我們可以取得臨時物件的控制權,終於可以修改臨時物件了!而且書上說配合move函式,可以大大...

C 11 右值引用與move語義

1.右值引用 1.1 右值 右值就是指在下乙個分號後 更準確的說是在包含右值的完整表示式的最後 銷毀的臨時物件。對於c 11,編譯器會依據引數是左值還是右值在複製建構函式和move建構函式間進行選擇。怎樣區分呢?the distinguishing criterion is if it has a ...