为什么std :: move采用通用引用? [英] Why does std::move take a universal reference?

查看:206
本文介绍了为什么std :: move采用通用引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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采用通用引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆