【问题标题】:C++ casting from lvalue reference to rvalue reference a unique_ptr从左值引用到右值引用的 C++ 转换引用 unique_ptr
【发布时间】:2014-12-14 10:54:57
【问题描述】:

我正在研究 C++ 中的完美转发机制,我对 std::move() 函数有一些疑问。这是一个可能的实现:

template<class T> 
typename remove_reference<T>::type&&
std::move(T&& a) noexcept {
  typedef typename remove_reference<T>::type&& RvalRef;
  return static_cast<RvalRef>(a);
}

std::unique_ptr&lt;&gt; 上使用时,此函数将资源的所有权从一个指针转移到另一个指针。 我发现这个函数的重点是从左值引用到右值引用到推导的T 类型的转换。

#include <iostream>
#include <memory>
using namespace std;
int main() {
    unique_ptr<int> p1(new int(20));
    unique_ptr<int> p2;
    unique_ptr<int> &r = p1;

    cout << "p1 = " << p1.get() << endl;
    cout << "p2 = " << p2.get() << endl;

    // These 2 instructions produce the same effect (then consider just one of them).
    p2 = static_cast<unique_ptr<int>&&>(r);
    //p2 = move(p1);

    cout << "p1 = " << p1.get() << endl;
    cout << "p2 = " << p2.get() << endl;

    return 0;
}

输出:

p1 = 0x467b10
p2 = 0
p1 = 0
p2 = 0x467b10

我想知道当我从 L 引用转换为 R 引用 std::unique_ptr&lt;int&gt; 类型时会发生什么。

【问题讨论】:

  • 没有运行时操作。这只是一种感知的表达方式的变化。这会影响在某些上下文中使用该表达式的操作,可能会导致(特别是重载决议)。

标签: c++ c++11 casting reference perfect-forwarding


【解决方案1】:

std::move 不动,std::forward 不转发。

move 只是将一种引用投射到另一种引用。它接受一个引用,并返回对相同数据的右值引用。这在运行时没有任何作用。移动的是消耗这个右值引用的代码。

该代码现在被告知“像对待临时未命名对象一样对待它”(不完全是,但很接近)。最常见的消费者是“移动构造函数”或“移动赋值”,这就是unique_ptr 的实际移动。

至于forward,这是一个有条件的移动,被定义为使用一种称为“完美转发”和/或“通用引用”的技术。它有时会移动,有时什么也不做。我之所以提到它,是因为我上面引用的那句精辟的说法提到了它:这是另一个话题。

【讨论】:

  • 迂腐:std::move 的单参数版本不动 :)
  • std::move 在运行时什么都不做,因为标准要求它,还是因为编译器会可能优化函数调用?我知道 - 正如你所说 - std::move 本身不做任何移动操作,但据我所知, std::move(a) 是一个标准的 STL 函数调用,绝不是 保证没有运行时成本。
  • 那么最好静态转换为右值引用而不是std::move()?
  • @MikeMB 该标准很少阻止编译器在任意点插入for (int i = 0; i &lt; 1 billion; ++i)。它甚至可以仅使用std::move 来实现。或者编译器可以将所述引用转换为指针,将指针压入堆栈,弹出相同的指针,然后调用它std::move。我会更加尊重第一个编译器,至少它的低效率是诚实的。但是,没有理由将一种引用类型转换为另一种作为强制转换应该在运行时执行任何操作。
  • @T.C.这句话很精辟,即使是假的也很有用。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 2014-10-31
  • 2011-02-14
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
相关资源
最近更新 更多