轉(zhuǎn)載--std::ref應(yīng)用

在std::promise范例中,使用了std::ref將future對(duì)象傳遞給引用參數(shù)類型的任務(wù)函數(shù)。

std::promise示例

如果直接傳入pr,將會(huì)出現(xiàn)編譯錯(cuò)誤:

error C2661: “std::tuple,std::promise>::tuple”: 沒有重載函數(shù)接受 2 個(gè)參數(shù)

說(shuō)明函數(shù)調(diào)用的參數(shù)類型不匹配。

查看thread的源代碼,其構(gòu)造函數(shù)依賴于一個(gè)rvalue-reference類型的variaic templates參數(shù)列表:

template::type, thread>::value>::type>explicit

thread(_Fn&& _Fx, _Args&&... _Ax){

// construct with _Fx(_Ax...)

_Launch(&_Thr,

_STD make_unique, decay_t<_Args>...> >(

_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));

}

其中的“_Args&&... _Ax”也是C++11引入的新特性:Variadic templates,它允許函數(shù)可以接受任意個(gè)不同類型的參數(shù),類似于C語(yǔ)言中的可變參數(shù)。在參考文檔[4]中說(shuō),”However, thanks tovariadic templates, programming new features usingtemplates has becomeeasier,clearer & morememory-efficient.“,為什么內(nèi)存效率更高呢?參考[6]中解釋說(shuō):參數(shù)列表所形成的一個(gè)parameter pack在編譯期間被解包,C++利用編譯期的處理實(shí)現(xiàn)了運(yùn)行時(shí)效率優(yōu)化。參考[5]中說(shuō):”Variadic templates are a trustworthy solution to implement delegates and tuples. And, instead of C-style ellipsis mechanism, variadic templates can offer a typesafer solution to replace them.“具體如何實(shí)現(xiàn)delegates和tuples,另行描述。

除了可變模板,另外兩個(gè)相關(guān)的新技術(shù)是rvalue-reference和reference_wrapper,這兩者和move語(yǔ)義是緊密相連的,如此節(jié)省了很多右值對(duì)象的復(fù)制構(gòu)造開銷。

std::ref(pr)返回的對(duì)象類型是一個(gè)reference_wrapper,而不是對(duì)pr的直接引用(T&,即std::promise&)。

換一個(gè)參考[7]中的例子:

bind與reference_wrapper的示例第一部分

上述代碼的結(jié)果是0!為什么?因?yàn)閎ind方法通過(guò)傳值方式傳入?yún)?shù),在被傳遞給綁定目標(biāo)add方法之前,變量”result“已經(jīng)被重新拷貝了。因?yàn)閎ind必須確保傳入的參數(shù)是持續(xù)可用的。

解決方法很簡(jiǎn)單,使用reference_wrapper:

bind與reference_wrapper的示例第二部分

使用如下代碼定義reference_wrapper對(duì)象:

?reference_wrapper r=x;// or auto r = ref(x);?

通過(guò)r對(duì)象的get函數(shù)(r.get()),r的作用與直接引用完全一樣。

還可以用來(lái)創(chuàng)建引用數(shù)組,例如:

引用數(shù)組的創(chuàng)建

std::reference_wrapper在泛型代碼中用處廣泛,它存儲(chǔ)的是對(duì)象的指針,有引用的全部功能,還實(shí)現(xiàn)了引用的拷貝(包括拷貝構(gòu)造和拷貝賦值),可以在程序中存儲(chǔ)引用而不是整個(gè)對(duì)象。

reference_wrapper和shared_ptr如何選擇??jī)烧叨伎梢詫?shí)現(xiàn)指針層面的復(fù)制和操作,但是前者不允許默認(rèn)構(gòu)造函數(shù),在容器中也不能使用resize等方法。另外可能還有一些不同之處,但是基本上沒有太大區(qū)別了。

參考資料:

[1] http://stackoverflow.com/questions/33240993/c-difference-between-stdreft-and-t

[2] http://stackoverflow.com/questions/26766939/difference-between-stdreference-wrapper-and-simple-pointer

[3] http://stackoverflow.com/questions/31013689/why-does-stdthread-take-function-to-run-by-rvalue

[4] http://softwareengineering.stackexchange.com/questions/273448/polymorphic-template-container-shared-ptr-vs-reference-wrapper

[5] http://www.cplusplus.com/articles/EhvU7k9E/

[6]Real-Time C++: Efficient Object-Oriented and Template Microcontroller Programming,2015-12,Christopher Kormanyos

[7] https://oopscenities.net/2012/08/09/reference_wrapper/

作者:Brent姜

鏈接:http://www.itdecent.cn/p/5b91c51bd856

來(lái)源:簡(jiǎn)書

簡(jiǎn)書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容