猫猫哥

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
/*##################################################################
 * 右值引用 (C++ 11)
 *     主要用于以下:
 *        1. 移动语义
 *        2. 完美传参 Perfect Forwarding
 */

/*
 * 什么是右值引用?
 */

int a = 5;
int& b = a;   // b是左值引用,在C++ 03叫做引用

int&& c       // c 右值引用


void printInt(int& i) { cout << "lvalue reference: " << i << endl; }
void printInt(int&& i) { cout << "rvalue reference: " << i << endl; } 

int main() {
   int i = 1;
   printInt(i);   // 调用第1个printInt
   printInt(6);   // 调用第2个printInt


   printInt(std::move(i));   // i是左值,先调move(),再调第2个printInt
}

/* 
 * 函数签名: 
 *
 *    int和int&不区分
 *    int和int&&不区分
 *
 *    int&和int&&区分,也就是可以重载左值引用和右值引用两个
 */





/* What's the big deal??? */

class boVector {
   int size;
   string label;
   double* array;
 public:
	boVector(const boVector& rhs) {  // 拷贝构造
      size = rhs.size; 
      array = new double[size];
      for (int i=0; i<size; i++) { array[i] = rhs.array[i]; }
   }
//	boVector(const boVector&& rhs) {  // 移动构造
 //     size = rhs.size; 
  //    array = rhs.array;
 //     rhs.array = nullptr;
  // }
};
void foo_by_value(boVector v) { v.label = "Student's Ages"; }       //如果没有右值引用,需要很多不同版本的函数
void foo_by_reference(boVector& v) { v.label = "Student's Ages"; }
boVector createBoVector();  // Creates a boVector

void main() {
   boVector reusable = createBoVector();
   foo_by_value(reusable);
   ...
   boVector tmp= createBoVector();
   foo_by_reference(tmp);
}


/* Notes:
	boVector(const boVector&& rhs) {  // 移动构造
      size = rhs.size; 
      array =  rhs.array;
   }

   boVector reusable = createBoVector();
   foo(reusable);
*/



// 练习:
boVecotor b = createBoVector();

// Approach 1: 
void foo(boVector & v);
foo(b);

// Approach 2: 
void foo(boVector && v);
foo(std::move(b));

// 问题:两种方法的相同点和不同点
// 两者参数传递上都不需要深拷贝
// 后者将所有权也传递, move后不能再使用



/* 
 * Note 1: 右值引用最主要的使用地方是重载拷贝构造和拷贝赋值,得到移动语义
 */
X& X::operator=(X const & rhs); 
X& X::operator=(X&& rhs);


/* Note 2: 所以得STL容器都实现了移动语义,这意味着:
 *    a. 只要切换到C++ 11,代码不做任何改变程序就能变快
 *    b. 使用值传递的频率更高了
 */

vector<int> foo() { ...; return myvector; } //可以直接返回

void goo(vector<int>& arg);   // 当需要使用参数将goo中处理之后的数据带回外面,需要用引用传递



/* 移动构造:
 *    目的:避免不必要的深拷贝
 * 1. 当既需要传引用又需要传值得时候,移动构造很有用
 * 2. 移动构造允许你对移动对象那个部分进行细微的控制
 */ 



// 陷阱:右值引用是一个右值么?

	boVector(const boVector && rhs) {
		cout << "Move constructor.\n";
		size = rhs.size;
      array = rhs.array;
      overload(rhs);
   }

   overload(boVector&  v) { cout << "by lvalue."; }
   overload(boVector&& v) { cout << "by rvalue."; }

posted on 2018-12-29 00:50  猫猫哥  阅读(293)  评论(0编辑  收藏  举报