/*##################################################################
* 右值引用 (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."; }