問題描述
為什么需要 std::reference_wrapper代碼>?應該在哪里使用?它與簡單的指針有何不同?與簡單的指針相比,它的性能如何?
Why is there a need to have std::reference_wrapper
? Where should it be used? How is it different from a simple pointer? How its performance compares to a simple pointer?
推薦答案
std::reference_wrapper
與模板結合使用非常有用.它通過存儲指向對象的指針來包裝對象,允許重新分配和復制,同時模仿其通常的語義.它還指示某些庫模板存儲引用而不是對象.
std::reference_wrapper
is useful in combination with templates. It wraps an object by storing a pointer to it, allowing for reassignment and copy while mimicking its usual semantics. It also instructs certain library templates to store references instead of objects.
考慮 STL 中復制函子的算法:您可以通過簡單地傳遞引用函子而不是函子本身的引用包裝器來避免這種復制:
Consider the algorithms in the STL which copy functors: You can avoid that copy by simply passing a reference wrapper referring to the functor instead of the functor itself:
unsigned arr[10];
std::mt19937 myEngine;
std::generate_n( arr, 10, std::ref(myEngine) ); // Modifies myEngine's state
這是有效的,因為......
This works because…
…
reference_wrapper
s 重載operator()
所以它們可以像它們引用的函數對象一樣被調用:
…
reference_wrapper
s overloadoperator()
so they can be called just like the function objects they refer to:
std::ref(myEngine)() // Valid expression, modifies myEngines state
...(un) 像普通引用一樣,復制(和賦值)reference_wrappers
只是賦值指針.
int i, j;
auto r = std::ref(i); // r refers to i
r = std::ref(j); // Okay; r refers to j
r = std::cref(j); // Error: Cannot bind reference_wrapper<int> to <const int>
復制一個引用包裝器實際上等同于復制一個指針,它盡可能便宜.使用它固有的所有函數調用(例如對 operator()
的調用)應該只是內聯,因為它們是單行的.
Copying a reference wrapper is practically equivalent to copying a pointer, which is as cheap as it gets. All the function calls inherent in using it (e.g. the ones to operator()
) should be just inlined as they are one-liners.
reference_wrapper
s 是通過 std::ref
創建的code> 和 std::cref
:
reference_wrapper
s are created via std::ref
and std::cref
:
int i;
auto r = std::ref(i); // r is of type std::reference_wrapper<int>
auto r2 = std::cref(i); // r is of type std::reference_wrapper<const int>
模板參數指定所引用對象的類型和cv-qualification;r2
引用一個 const int
并且只會產生對 const int
的引用.調用包含 const
函子的引用包裝器只會調用 const
成員函數 operator()
s.
The template argument specifies the type and cv-qualification of the object referred to; r2
refers to a const int
and will only yield a reference to const int
. Calls to reference wrappers with const
functors in them will only call const
member function operator()
s.
右值初始值設定項是不允許的,因為允許它們弊大于利.由于無論如何都會移動右值(并且使用 保證復制省略即使部分避免了這種情況),我們也不會改進語義;不過,我們可以引入懸空指針,因為引用包裝器不會延長指針的生命周期.
Rvalue initializers are disallowed, as permitting them would do more harm than good. Since rvalues would be moved anyway (and with guaranteed copy elision even that's avoided partly), we don't improve the semantics; we can introduce dangling pointers though, as a reference wrapper does not extend the pointee's lifetime.
如前所述,可以通過將相應的參數傳遞給 reference_wrapper
來指示 make_tuple
在結果 tuple
中存儲一個引用:
As mentioned before, one can instruct make_tuple
to store a reference in the resulting tuple
by passing the corresponding argument through a reference_wrapper
:
int i;
auto t1 = std::make_tuple(i); // Copies i. Type of t1 is tuple<int>
auto t2 = std::make_tuple(std::ref(i)); // Saves a reference to i.
// Type of t2 is tuple<int&>
請注意,這與 forward_as_tuple
略有不同:這里不允許將右值作為參數.
Note that this slightly differs from forward_as_tuple
: Here, rvalues as arguments are not allowed.
std::bind
顯示相同的行為:它如果它是一個 reference_wrapper
,則不會復制參數但存儲一個引用.如果該參數(或函子!)不需要復制但在使用 bind
-函子時保持在范圍內,則很有用.
std::bind
shows the same behavior: It won't copy the argument but store a reference if it is a reference_wrapper
. Useful if that argument (or the functor!) need not be copied but stays in scope while the bind
-functor is used.
沒有額外的語法間接層.指針必須被取消引用以獲得指向它們所引用對象的左值;
reference_wrapper
s 有一個隱式的轉換運算符并且可以被調用就像它們包裹的物體一樣.
There is no additional level of syntactical indirection. Pointers have to be dereferenced to obtain an lvalue to the object they refer to;
reference_wrapper
s have an implicit conversion operator and can be called like the object they wrap.
int i;
int& ref = std::ref(i); // Okay
reference_wrapper
與指針不同,它沒有空狀態.它們必須使用 引用或另一個 reference_wrapper
.
reference_wrapper
s, unlike pointers, don't have a null state. They have to be initialized with either a reference or another reference_wrapper
.
std::reference_wrapper<int> r; // Invalid
一個相似之處是淺拷貝語義:指針和 reference_wrapper
可以重新分配.
這篇關于std::reference_wrapper 和簡單指針的區別?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!