【问题标题】:Difference between std::forward implementationstd::forward 实现之间的区别
【发布时间】:2017-02-19 15:44:24
【问题描述】:

最近我一直在尝试理解移动语义并提出了一个问题。

这个问题已经讨论过here

我实现了第一个变体并检查它返回的是左值还是右值:

#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-value,它会返回 l-value(编译,因为我可以从 l-value 中获取地址)如果我这样做:

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

我的代码无法编译,因为 my_forward 返回了 r 值。在上面的问题中,他们说这个实现和标准实现之间的区别(分别使用 std::remove_reference 和 2 个不同的参数与 & 和 && )是我的实现一直返回左值,但正如我所展示的那样返回右值和左值。

所以我想知道,为什么我不能像那样实现 std::forward ?在什么特定情况下,它会显示标准之间的差异?还有,为什么要指定 T 为模板,又不能让它自己定义参数类型呢?

【问题讨论】:

  • 你为什么要获取r值引用的地址?
  • @BlackMoses 检查 r 值。
  • @LogicStuff 啊,好吧,还以为是对&amp;用法的误解:)
  • 检查它是右值还是左值。基本上是为了在链接的帖子中证明错误的第一个答案第一个问题是你可以编写 std::forward(x),它不会做你想要的,因为它总是产生左值引用。
  • 你真的应该用转发引用来测试它——你只能用模板参数来测试它。使用变量在 main 中进行测试,您不能将转发引用传递给您的 my_forward。

标签: c++ c++11 move-semantics c++-standard-library lvalue-to-rvalue


【解决方案1】:

在真实环境中尝试像 std forward 一样对它进行 hsing。你的不行;

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

所有有名字的都是左值,但是向前移动有名字的右值引用。

具有名称的右值引用是左值。

【讨论】:

  • 非常感谢!我用这个code 查了一下,看来我错了。我没有在真实的上下文中检查它,因为我(理论上)认为这些实现是相同的。我真的不明白有什么区别。你能解释一下吗?
  • 为什么我的实现是这样工作的?正如我们在主题中看到的,它返回 r-value,为什么它不起作用呢?
  • 有名字的右值引用是左值。直到你明白你会一直感到困惑。
  • 我想我明白这一点。我不明白的是为什么标准实现:typename remove_reference::type& t 与 T&& t 的工作方式不同。在函数体中它无论如何都是左值(因为它有一个名字)唯一的区别在于参数
  • @fminkin 获取foofoo&amp;foo&amp;&amp;foo const&amp; 类型并将它们分别提供给typename remove_reference&lt;T&gt;::type&amp;T&amp;&amp;。注意reference collapsing的规则。它们的工作方式不同,因为它们是非常不同的表达方式。例如,标准的引用不能永远是右值引用。他们怎么可能是一样的?
【解决方案2】:

不幸的是,获取地址在您的上下文中不是一个有用的操作,因为它查看了错误的值类别:

  • 您可以获取glvalue 的地址,但不能获取prvalue。 glvalue 表示“位置”(即对象所在的位置),prvalue 表示“初始化”(即对象具有什么值)。

  • 您可以从右值中窃取资源,但不能从左值中窃取。左值引用绑定到左值,右值引用绑定到右值。 std::forward 的要点是在提供右值时将参数强制转换为右值,在提供左值时将参数强制转换为左值。

std::forward返回右值的时候,其实是返回了一个xvalue,xvalues既是rvalues又是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

【讨论】:

  • 我想你的意思。 “你可以从右值窃取资源,但不能从左值窃取。”
猜你喜欢
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 2014-08-01
  • 2020-10-19
  • 2022-08-14
  • 2014-03-04
  • 2013-01-18
  • 2012-04-25
相关资源
最近更新 更多