int a = 5;
&
int a =5; int &ref_a =a; //左值引用,指向左值,编译通过 int &ref_a =5; //左值引用,指向右值,编译失败
&&
int &&ref_right =5; //编译通过 int a = 5; int &&ref_left = a; //编译不过,右值引用不可以指向左值 ref_right = 6; //右值引用的用途,可以修改右值
右值引用有办法指向左值吗?
std::move
int a = 5; //a是个左值 int &ref_left = a; //左值引用指向左值 int &&ref_right = std::move(a); //通过std::move将左值转化为右值,可以将右值引用指向 cout << a; //打印结果:5
在上面的代码里,看上去是左值a通过std::move移动到右值ref_right中,那是不是a里面就没有值了?并不是,打印出a的值仍然是5 。
std::move是一个具有迷惑性的函数,若单从字面上理解往往以为它能把一个变量里内容移动到另一个变量,但事实上std::move移动不了什么,唯一的功能是把左值强制转化为右值,让右值引用可以指向左值。所以单从的__std::move(xxx)并不会有性能提升__
同样的右值引用能指向右值,本质上也是把右值提升为一个左值,并定义一个右值引用通过std::move指向该左值:
int &&ref = 5; ref = 6; 等同于一下代码: int temp = 5; int &&ref = std::move(temp); ref = 6;
左值引用、右值引用本身是左值还是右值?
// 形参是个右值引用 void change (int && right_value){ right_value = 8; } int main(){ int a = 5; //a是一个左值 int &ref_left = a; //ref_left是一个左值引用 int &&ref_right = std::move(a); //ref_right是一个右值引用 change(a); //编译不过,a是左值,change参数要求右值 change(ref_left); //编译不过,左值引用ref_left本身也是个左值 change(ref_right); //编译不过,右值引用ref_right本身也是个左值 change(std::move(a)); //编译通过 change(std::move(ref_right)); //编译通过 change(std::move(ref_left)); //编译通过 chang(5); //当然可以直接接右值,编译通过 cout << &a << ' '; cout << &ref_left << ' '; cout << &ref_right; //打印这三个左值的地址,都是一样 }
int&&
int &&ref = std::move(a)
ref
从性能上将,左右值引用没有区别,传参使用左右值引用都可以避免拷贝。
右值引用可以直接指向右值,也可以通过std::move指向左值;而左值引用只能指向左值(const左值引用也能指向右值)
作为函数形参是,右值引用更加灵活。虽然const左值引用也可以做到左右值都接受,但它无法修改,有一定局限性。
class Array { public: Array(int size) : size_(size) { data = new int[size_]; } // 深拷贝构造 Array(const Array& temp_array) { size_ = temp_array.size_; data_ = new int[size_]; for (int i = 0; i < size_; i ++) { data_[i] = temp_array.data_[i]; } } // 深拷贝赋值 Array& operator=(const Array& temp_array) { delete[] data_; size_ = temp_array.size_; data_ = new int[size_]; for (int i = 0; i < size_; i ++) { data_[i] = temp_array.data_[i]; } } ~Array() { delete[] data_; } public: int *data_; int size_; };
class Array { public: Array(int size) : size_(size) { data = new int[size_]; } // 深拷贝构造 Array(const Array& temp_array) { ... } // 深拷贝赋值 Array& operator=(const Array& temp_array) { ... } // 移动构造函数,可以浅拷贝 Array(const Array& temp_array, bool move) { data_ = temp_array.data_; size_ = temp_array.size_; // 为防止temp_array析构时delete data,提前置空其data_ temp_array.data_ = nullptr; } ~Array() { delete [] data_; } public: int *data_; int size_; };
temp_array
temp_array.data_=nullptr;
Array(Array& temp_array,boolmove){...}
Array a = Array(Array(),trun);
std::vector
push_back
emplace_back
class Array { public: ...... // 优雅 Array(Array&& temp_array) { data_ = temp_array.data_; size_ = temp_array.size_; // 为防止temp_array析构时delete data,提前置空其data_ temp_array.data_ = nullptr; } public: int *data_; int size_; };
// 例1:Array用法 int main(){ Array a; // 做一些操作 ..... // 左值a,用std::move转化为右值 Array b(std::move(a)); }
int a =10; int & ref 1= a; //合法的 int & ref2 = 10; //× 不允许的,引用必须引一块合法的内存空间 const int & ref3 = 10; /*合法的,加上const后,编译器将代码修改为 int temp =10; const int & ref3 = temp; */