问题描述
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
右值?如果std::move
只接受左值,那会更有意义吗?
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(b + 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
}
上面的情况可能会出现在通用代码中,例如,当使用具有返回代理对象(rvalues)的特殊化的容器时,并且您可能不知道客户端是否将使用特殊化,因此您想要无条件的支持移动语义.
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具有向前引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!