【问题标题】:Forward or Move前进或移动
【发布时间】:2013-04-15 11:53:19
【问题描述】:
这些是移动和前进的有效用法吗?
f3 和 f4 是一样的吗?
这样做有危险吗?
谢谢!
#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
}
【问题讨论】:
标签:
c++
c++11
move-semantics
rvalue-reference
【解决方案1】:
所以f1 和f4 都是可行的解决方案。他们做不同的事情,所以你必须决定你想要哪一个。
不要使用f2 或f3。
【解决方案2】:
std::forward 的存在是因为 && 在类型推导下的工作方式存在一个怪癖。
在类型推导下,T&& 中的 T 将绑定到 3 种可能性之一。如果从左值int& 推导出来,T 将绑定到int&。那么int& && 只是一个int&。如果从左值int const& 推导出来,T 将绑定到int const&,并且int const& && 是int const&。如果从某种右值int 推导出来,T 将绑定到int,而int&& 是int&&。
std::forward 是一个用于反转该映射的实用函数。 std::forward<>的三个相关签名分别是:T& std::forward<T&>(T&)或T const& std::forward<T const&>(T const&)或T&& std::forward<T>(T&&)
在执行称为“完美转发”的技术时,所有这些最终都非常有用,您在类型推导上下文中使用 T&&t,然后使用 std::forward<T>(t) 传递从推导的“相同类型”到另一个电话。
请注意,上面有一些简化的谎言。例如,T const&& 也有可能在类型方面非常晦涩难懂。我可能忽略了类型推导如何工作的一些细节,而术语 rvalue 和 lvalue 并没有完全反映 C++11 中完整的 5 倍(或者是 6 倍?)不同类型的变量值.
【解决方案3】:
对于你的例子,他们会做同样的事情,但使用std::move 是惯用的
A f(A&& a) {
// use std::move(a)
}
函数模板稍有不同
template<typename A>
A f(A&& a) {
// use std::forward<A>(a)
}
不同之处在于第二个版本可以同时接收左值和右值(Scott Meyers 将它们命名为“universal references”),而第一个版本只能接收右值。