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?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Do the Java Integer and Double objects have unnece
- Why does const allow implicit conversion of refere
- thread_local variables initialization
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
You can think of it as a convenience wrapper around references so that you can use them in containers.
It's basically a
CopyAssignable
version ofT&
. Any time you want a reference, but it has to be assignable, usestd::reference_wrapper<T>
or its helper functionstd::ref()
. Or use a pointer.Other quirks:
sizeof
:And comparison:
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.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:
This works because…
…
reference_wrapper
s overloadoperator()
so they can be called just like the function objects they refer to:…(un)like ordinary references, copying (and assigning)
reference_wrappers
just assigns the pointee.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 are created viastd::ref
andstd::cref
:The template argument specifies the type and cv-qualification of the object referred to;
r2
refers to aconst int
and will only yield a reference toconst int
. Calls to reference wrappers withconst
functors in them will only callconst
member functionoperator()
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.
Library interaction
As mentioned before, one can instruct
make_tuple
to store a reference in the resultingtuple
by passing the corresponding argument through areference_wrapper
:Note that this slightly differs from
forward_as_tuple
: Here, rvalues as arguments are not allowed.std::bind
shows the same behavior: It won't copy the argument but store a reference if it is areference_wrapper
. Useful if that argument (or the functor!) need not be copied but stays in scope while thebind
-functor is used.Difference from ordinary pointers
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.reference_wrapper
s, unlike pointers, don't have a null state. They have to be initialized with either a reference or anotherreference_wrapper
.A similarity are the shallow copy semantics: Pointers and
reference_wrapper
s can be reassigned.Another difference, in terms of self-documenting code, is that using a
reference_wrapper
essentially disavows ownership of the object. In contrast, aunique_ptr
asserts ownership, while a bare pointer might or might not be owned (it's not possible to know without looking at lots of related code):There are, at least, two motivating purposes of
std::reference_wrapper<T>
:It is to give reference semantics to objects passed as value parameter to function templates. For example, you may have a large function object you want to pass to
std::for_each()
which takes its function object parameter by value. To avoid copying the object, you can usePassing arguments as
std::reference_wrapper<T>
to anstd::bind()
expression is quite common to bind arguments by reference rather than by value.When using an
std::reference_wrapper<T>
withstd::make_tuple()
the corresponding tuple element becomes aT&
rather than aT
: