简体   繁体   中英

Forward or Move

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM