C++ 从左值引用转换为右值引用unique_ptr

bar*_*-md 1 c++ casting reference perfect-forwarding c++11

我正在研究 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);
}
Run Code Online (Sandbox Code Playgroud)

当在 上使用时std::unique_ptr<>,此函数将资源的所有权从一个指针转移到另一个指针。我发现这个函数的焦点是从左值引用到右值引用到推导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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

p1 = 0x467b10
p2 = 0
p1 = 0
p2 = 0x467b10
Run Code Online (Sandbox Code Playgroud)

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

Yak*_*ont 5

std::move不动,std::forward不前进。

move只是将一种引用转换为另一种引用。它接受一个引用,并返回对相同数据的右值引用。这在运行时什么都不做。移动的是消耗这个右值引用的代码。

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

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

  • 迂腐:`std::move` 的单参数版本不移动 :) (2认同)