Are these valid usage of move and forward?
Are f3 and f4 the same?
Is it dangerous to do so?
Thank you!
#include <utility>
class A {};
A f1() {
A a;
return a; // Move constructor is called
}
A f2(A&& a) {
return a; // Copy constructor is called, which is what I try to avoid.
}
A f3(A&& a) {
return std::forward<A&&>(a); // Move constructor is called
}
A f4(A&& a) {
return std::move(a); // Move constructor is called
}
Use std::forward
with a universal reference , ie a template <typename T> ... T&&
.
Use std::move
with an rvalue reference (like your A&&
).
So both f1
and f4
are plausible solutions. They do different things, so you have to decide which one you want.
Do not use f2
or f3
.
std::forward
exists because of a quirk in how &&
works under type deduction.
Under type deduction, the T
in T&&
will bind to one of 3 possibilities. If being deduced from an lvalue int&
, T
will bind to int&
. Then int& &&
is just a int&
. If being deduced from an lvalue int const&
, T
will bind to int const&
, and int const& &&
is int const&
. If being deduced from an rvalue int
of some kind, T
will bind to int
, and int&&
is int&&
.
std::forward
is a utility function to reverse that map. The three pertinent signatures of std::forward<>
are: T& std::forward<T&>(T&)
or T const& std::forward<T const&>(T const&)
or T&& std::forward<T>(T&&)
All of this ends up being exceedingly useful when doing the technique known as "perfect forwarding", where you use T&&t
in a type deduction context, then std::forward<T>(t)
to pass on the "same type" as was deduced from to another call.
Note that there are a few simplifying lies above. There are is also the possibility of T const&&
which is pretty obscure type-wise, as an example. I probably glossed over some details of how the type deduction works, and the terms rvalue
and lvalue
don't fully reflect the full 5-fold (or is it 6?) different kinds of variable values in C++11.
For your example, they will do the same thing, but it is idiomatic to use std::move
A f(A&& a) {
// use std::move(a)
}
A slightly different case is with function templates
template<typename A>
A f(A&& a) {
// use std::forward<A>(a)
}
The difference is that the second version can receive both lvalues and rvalues (Scott Meyers named them " universal references "), whereas the first version can only receive rvalues.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.