- 看到一個用法
- 容器裏是 std::reference_wrapper 對象
std::vector<std::reference_wrapper<ParticipantObserver>> observers_;
- 總結了下,可能以下三種情況需要用到:
- vector裏不能直接存儲引用,又不想做拷貝
- 丟入lamba或者函數是引用,
- 如果設計意圖就是執行完畢後被對象會被修改
C++11爲什麼需要std::ref/reference_wrapper?
在std::promise範例中,使用了std::ref將future對象傳遞給引用參數類型的任務函數。
- std::promise示例
- 如果直接傳入pr,將會出現編譯錯誤:
error C2661: “std::tuple,std::promise>::tuple”: 沒有重載函數接受 2 個參數
-
說明函數調用的參數類型不匹配。
-
查看thread的源代碼,其構造函數依賴於一個rvalue-reference類型的variaic templates參數列表:
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,
它允許函數可以接受任意個不同類型的參數,類似於C語言中的可變參數。
在參考文檔[4]中說,”However, thanks to variadic templates, programming new features using templates has become easier, clearer & more memory-efficient.“,
爲什麼內存效率更高呢?參考[6]中解釋說:參數列表所形成的一個parameter pack在編譯期間被解包,C++利用編譯期的處理實現了運行時效率優化。
參考[5]中說:”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.“具體如何實現delegates和tuples,另行描述。
-
除了可變模板,另外兩個相關的新技術是rvalue-reference和reference_wrapper,這兩者和move語義是緊密相連的,如此節省了很多右值對象的複製構造開銷。
-
std::ref(pr)返回的對象類型是一個reference_wrapper,而不是對pr的直接引用(T&,即std::promise&)。
-
換一個參考[7]中的例子:
-
bind與reference_wrapper的示例第一部分
-
上述代碼的結果是0!爲什麼?因爲bind方法通過傳值方式傳入參數,在被傳遞給綁定目標add方法之前,變量”result“已經被重新拷貝了。因爲bind必須確保傳入的參數是持續可用的。
-
解決方法很簡單,使用reference_wrapper:
-
bind與reference_wrapper的示例第二部分
-
使用如下代碼定義reference_wrapper對象:
reference_wrapper r=x;// or auto r = ref(x);
- 通過r對象的get函數(r.get()),r的作用與直接引用完全一樣。
引用數組的創建
- 還可以用來創建引用數組,例如:
- std::reference_wrapper在泛型代碼中用處廣泛,它存儲的是對象的指針,有引用的全部功能,還實現了引用的拷貝(包括拷貝構造和拷貝賦值),可以在程序中存儲引用而不是整個對象。
- reference_wrapper和shared_ptr如何選擇?兩者都可以實現指針層面的複製和操作,但是前者不允許默認構造函數,在容器中也不能使用resize等方法。另外可能還有一些不同之處,但是基本上沒有太大區別了。
參考資料:
[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/