右值系列之六 向前,向前!

2021-05-27 17:57:05 字數 1833 閱讀 2806

除了提供轉移語義,右值引用的另乙個主要用途是解決「完美**」。在這裡,「**」的指將乙個泛型函式的實參**至另乙個函式而不會拒絕掉第二個引數可接受的任何引數,也不會丟失關於這些引數的cv限定或左右值屬性的任何資訊,而且還無須採用過載。在c++03中,最佳的近似是將所有右值變為左值,並且需要兩個過載。

考慮以下例子:

private:

f f;};

這種方式是不行的,因為我們的函式呼叫操作符是傳值的,它會拒絕所有不可複製/不可轉移的型別,即便 f 可以接受這些型別。如果我們把它改為:

template void operator()( argumenttype& x )
那麼我們會拒絕所有非常量性的右值。我們可以加乙個過載:

template void operator()( argumenttype& x ) 

template void operator()( argumenttype const& x )

對於右值引用,我們可以利用一些特殊設計的語言規則來解決這個問題:

template void operator()( argumenttype && x )

這兩個特殊規則是:

關於右值引用消除的規則。在c++0x中,很早以前就決定了如果 t 為 u&,則 t& 也為 u&。這是左值引用消除。而對於右值引用,規則被更改為:

& + & 變為 &

& + && 變為 &

&& + & 變為 &

&& + && 變為 &&

即,任一」左值性」都會令結果變為左值。

關於推定「全泛化右值引用」引數(如上例中的 argumenttype)的規則。該規則規定,如果實參是乙個右值,則 argumenttype 被推定為非引用型別,而如果實參是乙個左值,則 argumenttype 則被推定為左值引用型別。

當實參為型別 y 的右值時,這兩個規則的結果是:argumenttype 被推定為 y,因此這裡只有乙個引用且沒有被消除:函式的引數型別為 y&&。

當實參是型別 y 的左值時,argumenttype 被推定為 y& (或 y const&),且引用消除規則會起作用,使得例項化的函式的引數型別為 y& && 即 y&...它剛好被繫結到乙個左值。

最後乙個要點是 forward 函式,它的任務是,當 argumenttype 為非引用時,「重建」實參的右值性,從而無干擾地把它傳遞給 f。

和 std::move 一樣,std::forward 是乙個零開銷的操作。雖然它不是乙個真正的轉換,但是你可以把 std::forward(x) 想象為 static_cast(x) 的描述性表示:當實參是乙個右值時,我們把 x 轉型為乙個匿名右值引用,但是當實參是乙個左值時,argumenttype 就是乙個左值引用且引用消除會起作用,因此 static_cast 的結果仍是乙個左值引用。

最近,關於 forward 的定義是否應該進行調整以適用於除「完美**」以外的用途,產生了一些實質性的異議,這些其它用途包括:用於類似於 std::tuple 這樣的型別的轉移建構函式,這些型別可能含用引用成員,並且要防止將左值引用繫結到右值成員這樣的危險情形。被建議的調整通常被稱為幫助你「把乙個 x 當作乙個 y 來**」。有關這些調整的細節,請參考 n2951。

我從來沒有認同過這個方向的調整,因為「**乙個函式的實參並保持它們的cv限定及右值性」對我來說非常有意義,而「把 x 當作 y 來**」則沒有明顯的意義。換句話說,這種 forward 如何使用以及為何要用,並沒有明顯的心理模型:我們沒有與之對應的程式設計模型。我最終放棄對此的抵抗,這是因為我看到,它在某些使用者必須要處理的與類相關的一些問題方面是有用的,但是我仍然認為,我們必須指出它的意義所在,並且把它解釋清楚。

matlab Newton向前插值

本文章由計算機專業的孫旭編寫,複製請謹慎 function fun clc x 0 1 2 3 y 1 2 17 64 x0 0.5 h 1 new front x,y,x0 end 子函式 function new front x,y,x0,h len x length x len y lengt...

糾錯技術之FEC(向前糾錯)

糾錯碼 error correcting code 在傳輸過程中發生錯誤後能在收端自行發現或糾正的碼。僅用來發現錯誤的碼一般常稱為檢錯碼。為使一種碼具有檢錯或糾錯能力,須對原碼字增加多餘的碼元,以擴大碼字之間的差別 即把原碼字按某種規則變成有一定剩餘度 見信源編碼 的碼字,並使每個碼字的碼之間有一定...

右值系列之四 再論賦值

view plain mutex m1,m2 std vector v1,v2 v1.push back shared ptr new lock m1 v2.push back shared ptr new lock m2 v2 v1 1 v2 std move v1 2 done with v1 ...