std::reference_wrapper is useful in combination with templates. It wraps the object, keeping a pointer to it, allowing you to reassign and copy, simulating the usual semantics. He also instructs certain library templates to store links instead of objects.
Consider the algorithms in STL that functors copy: you can avoid this copy by simply passing a reference wrapper with a reference to the functor instead of the functor itself:
unsigned arr[10]; std::mt19937 myEngine; std::generate_n( arr, 10, std::ref(myEngine) );
This works because ...
... reference_wrapper overload operator() so that they can be called in the same way as the objects of the functions to which they refer:
std::ref(myEngine)()
... (un) like regular links, copying (and assigning) reference_wrappers just assigns a pointee.
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>
Copying a reference wrapper is almost equivalent to copying a pointer, which is just as cheap as it is. All function calls inherent in its use (for example, those specified in operator() ) should simply be inlined, as they are single-line.
reference_wrapper are created using 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>
The template argument indicates the type and cv qualification of the referenced object; r2 refers to const int and gives only a reference to const int . Calls for reference wrappers with const functors in them will only call the const member function operator() s.
Rvalue initializers are not allowed, as this gives them more harm than good. Since rvalues ββwill move anyway (and with guaranteed copy permission , even if this is partially avoided), we do not improve the semantics; we can introduce dangling pointers, though, since the reference shell does not extend the life of the pointer.
Library Interaction
As mentioned earlier, you can tell make_tuple to save the link in the resulting tuple by passing the corresponding argument through reference_wrapper :
int i; auto t1 = std::make_tuple(i);
Note that this is slightly different from forward_as_tuple : Here rvalues ββare not valid as arguments.
std::bind shows the same behavior: it does not copy the argument, but saves the link if it is reference_wrapper . Useful if this argument (or functor!) Does not need to be copied, but remains in scope while using bind functor.
Unlike regular pointers
There is no additional level of syntactic indirection. Pointers must be dereferenced to get an lvalue to the object they are referencing; reference_wrapper have an implicit conversion operator and can be called as the object they wrap.
int i; int& ref = std::ref(i);
reference_wrapper s, unlike pointers, do not have a null state. They must be initialized by reference or another reference_wrapper .
std::reference_wrapper<int> r;
Similarity is the odd semantics of a copy: pointers and reference_wrapper can be reassigned.