接前面文章继续,先看使用右值引用的代码:
#include <iostream>
using namespace std;
class MyBlob
{
private:
char* m_p;
int m_size;
public:
MyBlob(): m_p(nullptr), m_size(0) {}
MyBlob(int size)
{
m_p = new char[size];
m_size = size;
cout << "Construct " << m_size << " bytes" << endl;
}
~MyBlob()
{
if(!m_p)
{
delete[] m_p;
m_p = nullptr;
}
m_size = 0;
}
MyBlob(const MyBlob& b)
{
cout << "Copy Construct " << endl;
m_size = b.m_size;
m_p = new char[m_size];
memcpy(m_p, b.m_p, m_size);
}
MyBlob& operator=(const MyBlob& b) //拷贝赋值
{
cout << "Copy assignment......" << endl;
if (!m_p)
{
delete[] m_p;
}
m_size = b.m_size;
m_p = new char[m_size];
memcpy(m_p, b.m_p, m_size);
return *this;
}
MyBlob& operator=(MyBlob&& b) noexcept //移动赋值,参数为右值引用
{
cout << "Move assignment ......" << endl;
if (!m_p)
{
delete[] m_p;
}
m_p = b.m_p;
m_size = b.m_size;
b.m_p = nullptr;
b.m_size = 0;
return *this;
}
void print()
{
cout << "this = " << static_cast<void*>(this) << ", addr " << static_cast<void*>(m_p) << ",size = " << m_size << endl;
}
};
int main()
{
MyBlob a(10);
MyBlob b1(100);
b1 = a; //调用拷贝赋值函数
MyBlob b(100);
MyBlob b2(100);
b2 = move(b); //调用移动赋值函数
}
如果在类中重载了移动赋值函数,那么代码:b1 =a 就会调用拷贝赋值函数,而代码b2 = move(b)则调用移动赋值函数。move(b)的作用就是把左值引用转为右值引用。
由此我们得出结论,之所以引入右值引用,其实就是为了能够根据参数不同来调用不同的赋值函数。如果赋值操作的右边参数为左值引用,那么调用拷贝赋值函数,反之如果为右值引用,则调用移动赋值函数。这个是由系统编译的时候来确定的。并且如果进行了移动赋值,那么被移动的对象则不可再使用,因为其内存所有权已经移交给被赋值的对象。