C++ 为什么std::当类型已经是T&;类型时移动&;

C++ 为什么std::当类型已经是T&;类型时移动&;,c++,c++11,C++,C++11,我在今天人们的回答中看到了一些地方,比如说我有Foo的构造函数 Foo( std::vector<SomeType>&& data) noexcept : data_(std::move(data)) {}; Foo(std::vector&&data)noexcept:data(std::move(data)){; 为什么std::move(data)是必需的,因为数据的类型不是std::vector&& 在我看来,std::move只是将数据再次强制

我在今天人们的回答中看到了一些地方,比如说我有Foo的构造函数

Foo(      std::vector<SomeType>&& data) noexcept : data_(std::move(data)) {};
Foo(std::vector&&data)noexcept:data(std::move(data)){;
为什么std::move(data)是必需的,因为数据的类型不是std::vector&&

在我看来,std::move只是将数据再次强制转换为std::vector&&

定义std::移动为

static_cast<typename std::remove_reference<T>::type&&>(t)
static_cast(t)
因此,在本例中,std::move似乎又是无关紧要的,但我可能遗漏了一些东西

在这两种情况下

void foo(const T& bar); // 1
void foo(T&& bar);      // 2
bar
实际上是一个
左值。
&&
的意思是重载
2
将绑定到右值,例如在以下情况下:

foo(Bar());
而重载
1
将在此处绑定:

T bar;
foo(bar);
2
中,您仍然需要使用
std::move
使
bar
的外观和行为类似于函数内部的
rvalue

在这两种情况下

void foo(const T& bar); // 1
void foo(T&& bar);      // 2
bar
实际上是一个
左值。
&&
的意思是重载
2
将绑定到右值,例如在以下情况下:

foo(Bar());
而重载
1
将在此处绑定:

T bar;
foo(bar);

2
中,您仍然需要使用
std::move
使
bar
在函数内部的外观和行为类似于
rvalue

我明白了。我猜这是因为命名的右值引用仍然是左值。本文对此进行了详尽的解释。>声明为右值引用的对象可以是左值或右值。区别标准是:如果它有一个名称,那么它就是一个左值。否则,它是一个右值。@capturesteve是的,就是它。而且
std::move
主要是一个隐藏名字的把戏。我明白了。我猜这是因为命名的右值引用仍然是左值。本文对此进行了详尽的解释。>声明为右值引用的对象可以是左值或右值。区别标准是:如果它有一个名称,那么它就是一个左值。否则,它是一个右值。@capturesteve是的,就是它。而
std::move
主要是一种隐藏名称的技巧。