c – 为什么std :: move采用前向引用?

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 ::移动左值和右值:

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)的特化的容器时,您可能不知道客户端是否将使用特化,因此您希望无条件支持移动语义.

上一篇:c – 隐式生成的赋值运算符是否应该是&ref-qualified?


下一篇:c-具有已选择具有非const ref的复制构造函数的参数类型的函数?