问题描述
std :: move
的实现基本上如下所示:
The implementation of std::move
basically looks like this:
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
同时使用左值和右值:
Note that the parameter of std::move
is a universal reference (also known as a forwarding reference, but we're not forwarding here). That is, you can std::move
both lvalues and rvalues:
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
只接受lvalues,这样会更有意义吗?
But since the whole point of std::move
is to cast to an rvalue, why are we even allowed to std::move
rvalues? Wouldn't it make more sense if std::move
would only accept lvalues?
template<typename T>
T&&
move(T& t)
{
return static_cast<T&&>(t);
}
然后无意义的表达式 std :: move + c)
会导致编译时错误。
Then the nonsensical expression std::move(b + c)
would cause a compile-time error.
上述实现 std :: move
对于初学者来说也会更容易理解,因为代码完全按照它看起来做的:它需要一个左值,并返回一个右值。
The above implementation of std::move
would also be much easier to understand for beginners, because the code does exactly what it appears to do: It takes an lvalue and returns an rvalue. You don't have to understand universal references, reference collapsing and meta functions.
那么为什么 std :: move
So why was std::move
designed to take both lvalues and rvalues?
推荐答案
这里是一些简化到极端的例子:
Here is some example simplified to the extreme:
#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
}
像上面这样的案例可能会出现在通用代码,例如当使用具有返回代理对象(rvalue)的专门化的容器,并且您可能不知道客户端是否将使用专门化,所以您希望无条件支持移动语义。
Cases like the one above may appear in generic code, for example when using containers which have specializations that return proxy objects (rvalues), and you may not know whether the client will be using the specialization or not, so you want unconditional support for move semantics.
这篇关于为什么std :: move采用通用引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!