右值引用那些事儿 - 简书
c++11中,能使用右值引用持续延长将亡值的寿命吗? - 知乎
C/C++学习记录:std::move 源码分析_河边小咸鱼的博客-CSDN博客_c++ move源码
临时变量右值引用
左常引用和右值引用都可以把临时对象的生命周期延长到与引用自身的生命周期相同。
说到实现,其实是变量替换,临时变量直接被构建在引用变量的位置,生命周期自然相同了。
T f() {
return T{};
}
T&& a= f();
//a继续有效
被编译器看成
void f(T& temp){
temp = ... 直接构造,不会走复制或移动构造函数
}
T a;
f(a);
//a继续有效。
右值引用本质
看不出右值引用对普通基本数据有任何实际意义,但是大量文章使用基本数据来讲解,完全没有讲到有意义的点子上,这样过于简化讲解,容易误导、困惑初学者。右值引用真正用意,是用于解决类对象内部拥有的动态数据的回收(转移),提高程序运行效率。普通数据对右值引用的适用,仅仅是个副产品。
我们再看一个移动构造函数的具体实现,方便大家理解move语义存在的价值:
class MyVector {
int* data_;
size_t size_;
public:
MyVector(): size_(100) {
data_ = new int[size_];
}
~MyVector() {
delete[] data_;
}
MyVector(const MyVector& my_vector) { // Copy constructor
size_ = my_vector.size_;
data_ = new int[size_];
std::copy(my_vector.data_, my_vector.data_ + my_vector.size_, data_);
}
MyVector(MyVector&& my_vector) { // Move constructor
size_ = my_vector.size_;
data_ = my_vector.data_;
my_vector.size_ = 0;
my_vector.data_ = nullptr;
}
// Should define copy assignment operator here
// Should define move assignment operator here
};
MyVector my_vector;
MyVector my_vector1 = my_vector; // my_vector is lvalue, thus copy constructor is invoked.
MyVector my_vector2 = std::move(my_vector); // std::move(my_vector) is rvalue, thus move constructor is invoked.
这里,我们实现了一个简单的数组类,自定义了拷贝构造函数和移动构造函数。在拷贝构造函数中,把旧data_ 数组中的每个元素依次赋值到新的对象中。在移动构造函数中,直接把旧data_ 数组的指针赋值给新对象,从而避免了数据的拷贝。但移动后,需要把旧对象的size_ 标记为0,把data_ 指针置空,以表示所有权的转移。这个简单的例子揭示了移动语义存在的价值,因为有些情况下,数据是可以转移所有权的,而不必拷贝一份。
|