翻译「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」的话,那么你已经从本质上看到了右值引用的定义。

posted on 2015-01-13 01:02  harryttt  阅读(761)  评论(0编辑  收藏  举报

导航