在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)并注明出處。