0

最近我一直在尝试理解移动语义并提出了一个问题。std :: forward实现之间的区别

该问题已被讨论here

我实现了第一个变种,并检查其是否返回L值或R值:

#include <iostream> 
using namespace std; 

template <typename T> 
T&& my_forward(T&& x) { 
    return static_cast<T&&> (x); 
} 

int main() { 
    int a = 5; 
    &my_forward(a); // l-value 
    return 0; 
} 

所以,如果我通过L值,则返回L值(编译,因为我可以如果我这样做:

&my_forward(int(5)); // r-value with int&& type 

我的代码不编译,因为my_forward返回的r值。在上面的问题中,他们说这个实现和标准的区别(分别是std :: remove_reference和两个不同的参数分别是&和& &)是我的实现始终返回l值,它会返回r值和l值。

所以我想知道,为什么我不能实现std :: forward像那样?在哪些具体情况下会显示标准版本之间的区别?另外,为什么我应该将T指定为模板并且不能让它使用参数类型来定义它自己?

+0

你为什么试图采取的右值引用地址? – xinaiz

+0

@BlackMoses检查r值。 – LogicStuff

+0

@LogicStuff啊,好吧,以为这是误判'&'的用法:) – xinaiz

回答

3

尝试在真实环境中将它像std一样向前。你的不工作;

void test(std::vector<int>&&){} 

template<class T> 
void foo(T&&t){ 
    test(my_forward<T>(t)); 
} 

foo(std::vector<int>{}); 

以上不编译。它与std::forward

除了块参考寿命延长之外,您的转发没有任何用处。同时,std::forward是条件std::move

带名称的东西都是左值,但是向前移动右值引用的名称。

带名称的左值引用是左值。

+0

非常感谢!我检查了这个[代码](http://ideone.com/XPePam),似乎我错了。我没有在真实的环境中检查它,因为我认为(实际上)这些实现是相同的。我真的不明白有什么区别。你能解释一下吗? – fminkin

+0

为什么我的实现像这样工作?正如我们在主题中看到的那样,它返回r值,为什么它不起作用呢? – fminkin

+0

**带名称的右值引用是左值。**直到您明白您将会感到困惑。 – Yakk

1

不幸的是,服用地址是不是在你的背景下有用的操作,因为它着眼于一种错误的价值范畴的:

  • 你可以采取glvalue的地址,而不是prvalue的。一个glvalue代表一个“位置”(即一个对象所在的位置),一个prvalue代表“初始化”(即一个对象有什么值)。

  • 您可以从右值盗取资源,但不能从左值盗取资源。左值引用绑定到左值,左值引用绑定到右值。 std::forward的要点是在提供右值时向右值赋值,当赋值左值时赋值为左值。

std::forward返回一个右值,它实际上返回一个x值,和xvalues都是右值和glvalues:

    lvalue  f() for "T& f();", decltype(f()) is T& 
       /
      glvalue 
     /  \ 
    value    xvalue  f() for "T&& f();", decltype(f()) is T&& 
     \  /
      rvalue 
        \ 
        prvalue  f() for "T f();", decltype(f()) is T 
+0

我认为你的意思。 “你可以从右值盗取资源,但不能从左值盗取资源。” – Lenz

+0

@Lenz:我没有,谢谢:-) –

相关问题