首页 > 代码库 > 翻译「C++ Rvalue References Explained」C++右值引用详解 Part2:Move语义

翻译「C++ Rvalue References Explained」C++右值引用详解 Part2:Move语义

本文为第二部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/4220233.html。

Move语义

假设x是一个类,其含有一个指针或者某些资源的句柄(handle)。写作m_pResource。由这个资源,我的意思是包括构造、克隆、析构都认真考虑在内的,一个绝佳的例子是std::vector。它可以在一个分配的内存数组中包含一个对象集合。接下来,从逻辑上,对于x的拷贝赋值操作符一般如下:

X& X::operator=(X const & rhs){  // [...]  // 析构 m_pResource指向的资源.   // 对rhs.m_pResource所指向的资源做一份克隆,然后  // 再把它附在 m_pResource上.  // [...]}

因为类似的原因这也适用于拷贝构造函数。现在假设x被如下使用:

X foo();X x;// x也许被通过多种方式使用x = foo();

在最后一行执行前:

  • 析构了被x持有的资源
  • 克隆了从foo返回的临时变量
  • 析构了那个临时变量并从而释放了它指向的资源

显而易见的,这样是可行的,但还有一种更有效率的做法,那就是交换(swap)x和临时变量中的对资源的指针或者句柄(handles),然后让临时变量的析构器析构原来x的资源。换一种说法,在这种特别的情况下,位于赋值右手边的是右值。我们希望拷贝构造函数如下表现:

// [...]// 交换m_pResource和rhs.m_pResource// [...]

这被称作Move语义。在C++11中,这种条件性的行为可以通过如下重载来实现:

X& X::operator=(<mystery type> rhs){  // [...]  // 交换this->m_pResource和rhs.m_pResource  // [...]  }

因为我们定义了一个对于拷贝构造函数的重载,我们的「mystery type」必须本质上是一个引用:我们当然想让右手边的值可以通过引用传递给我们。而且,我们期望mystery type有如下的行为:当面临到原始的引用类型和mystery type的重载选择时,右值一定优先选择mystery type的重载,而左值一定优先选择原始的引用类型。

如果你现在意识到在上文中「右值引用」就是指代「mystery type」的话,那么你已经从本质上看到了右值引用的定义。

翻译「C++ Rvalue References Explained」C++右值引用详解 Part2:Move语义