1. 左值、右值
左值:有地址的变量就是左值;
右值:没有地址的字面值、临时值;
int a = 5; // a为左值、5为右值
A a = A(); // a为左值、A()为右值
2. 左值引用、右值引用
左值引用:&,
int a = 5;
int &ref_l = a;
int &ref_l = 5; // error, 左值引用指向了右值
例外:const int &ref_a = 5; //编译通过,const自己创建了一个变量,ref_a指向了该变量
右值引用:&&
int &&ref_r = 5;
int a = 5;
int &&ref_r = a; // error, 右值引用指向了左值
左值转为右值:std::move(),强转,等同于static_cast<T&&>(l_value)
int a = 5;
int && ref_r = std::move(a)
==> 右值引用& 可以指向右值、也可以通过std::move()指向左值;左值引用&& 虽然可以通过const指向右值,但无法修改;
==> 作为形参传递时,右值更灵活。
3. 使用
class Array {
public:
int *data_;
int size_;
public:
Array(int size) : size_(size) {
data = new int[size_];
}
// 深拷贝构造, data_为空
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];
}
// 深拷贝赋值, data_不为空
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(Array&& temp_array) {
// 若为 Array(Array& temp_array),无法使用Array a = Array(Array()),左值引用无法接右值
data_ = temp_array.data_;
size_ = temp_array.size_;
// 为防止temp_array析构时delete data,提前置空其data_
temp_array.data_ = nullptr;
}
~Array() {
delete[] data_;
}
};
// 例1:Array用法
int main(){
Array a;
// 左值a,用std::move转化为右值
Array b(std::move(a));
}