[英]Why does std::move take a forward reference?
std::move
的实现基本上如下所示:
template<typename T>
typename std::remove_reference<T>::type&&
move(T&& t)
{
return static_cast<typename std::remove_reference<T>::type&&>(t);
}
请注意, std::move
的参数是通用引用(也称为转发引用,但我们不在此处转发)。 也就是说,你可以std::move
左值和右值:
std::string a, b, c;
// ...
foo(std::move(a)); // fine, a is an lvalue
foo(std::move(b + c)); // nonsense, b + c is already an rvalue
但是因为std::move
是强制转换为右值,为什么我们甚至允许std::move
rvalues呢? 如果std::move
只接受左值,那会不会更有意义?
template<typename T>
T&&
move(T& t)
{
return static_cast<T&&>(t);
}
然后无意义的表达式std::move(b + c)
会导致编译时错误。
对于初学者来说, std::move
的上述实现也会更容易理解,因为代码完全按照它的样子执行:它需要一个左值并返回一个右值。 您不必了解通用引用,引用折叠和元函数。
那么为什么std::move
设计为同时采用左值和左值?
以下是一些简化为极端的示例:
#include <iostream>
#include <vector>
template<typename T>
T&& my_move(T& t)
{
return static_cast<T&&>(t);
}
int main()
{
std::vector<bool> v{true};
std::move(v[0]); // std::move on rvalue, OK
my_move(v[0]); // my_move on rvalue, OOPS
}
像上面这样的情况可能出现在通用代码中,例如当使用具有返回代理对象(rvalues)的特化的容器时,您可能不知道客户端是否将使用特化,因此您希望无条件支持移动语义。
它没有伤害。
您只是建立了一个保证代码将结果视为右值的保证。 你当然可以编写std :: move,以便在处理已经是rvalue的东西时出错,但有什么好处呢?
在通用代码中,你不一定知道你将要使用什么类型,你会从一堆“如果类型是rvalue什么都不做std :: move”中提取出表现力的增益。当你可以简单地说“我保证我们可以把它想象成一个左值”时,到处都贴满了。
你自己说过,它只不过是演员。 如果参数已经与预期类型匹配,* _cast操作是否也会失败?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.