【发布时间】:2016-02-12 20:38:40
【问题描述】:
here 的示例 std::forward,
// forward example
#include <utility> // std::forward
#include <iostream> // std::cout
// function with lvalue and rvalue reference overloads:
void overloaded (const int& x) {std::cout << "[lvalue]";}
void overloaded (int&& x) {std::cout << "[rvalue]";}
// function template taking rvalue reference to deduced type:
template <class T> void fn (T&& x) {
overloaded (x); // always an lvalue
overloaded (std::forward<T>(x)); // rvalue if argument is rvalue
}
int main () {
int a;
std::cout << "calling fn with lvalue: ";
fn (a);
std::cout << '\n';
std::cout << "calling fn with rvalue: ";
fn (0);
std::cout << '\n';
return 0;
}
Output:
calling fn with lvalue: [lvalue][lvalue]
calling fn with rvalue: [lvalue][rvalue]
提到
所有命名值(例如函数参数)总是 评估为左值(即使是那些声明为右值引用的)
然而,典型的移动构造函数看起来像
ClassName(ClassName&& other)
: _data(other._data)
{
}
看起来像_data(other._data) 应该调用_data 类的移动构造函数。但是,不使用std::forward 怎么可能呢?换句话说,不应该吗
ClassName(ClassName&& other)
: _data(std::forward(other._data))
{
}
?
因为正如在 std:forward 案例中指出的那样,
所有命名的值都应该评估为左值
我越来越喜欢 C++,因为这样的问题有深度,而且语言足够大胆,可以提供这样的功能:) 谢谢!
【问题讨论】:
-
您应该在构造函数中使用
std::move。见:How to define a move constructor? -
“然而,典型的移动构造函数看起来像......”不,它没有。此外,
std::forward用于 转发 事物作为它们的原始值类别,可以是右值或左值,具体取决于与std::forward一起使用的模板参数。只是说std::forward(other._data)没有模板参数列表甚至不会编译。如果您只想要一个右值,请使用std::move而不是std::forward。 -
@JonathanWakely 但是如果参数是左值 ClassName(ClassName&& other) 甚至不会被调用,因为函数原型不匹配。
-
@user557583,它可能以右值开始,但一旦你进入构造函数,它就有一个名称并且是一个左值。阅读转发引用的工作原理。这不是您使用
std::forward的方式,也不是您编写移动构造函数的方式。
标签: c++ c++11 move-semantics rvalue move-constructor