首先,在c++语言中,有一些数值,他们只能放在等号右边,只能用于对左值赋值,这样的数值称之为右值;右值通常是一些数值变量、临时变量和无名变量等。
而对于右值引用,在c++语言中,通过运算符“&&”来声明一个右值引用,对于之前的左值引用(即我们常说的引用),通过运算符“&”来声明引用。
这相关知识又与拷贝构造函数有关。
右值引用至少解决了这两个问题:
实现move语义
完美转发
可以用这样判断左右值:
左值是一个指向某内存空间的表达式,并且我们可以用&操作符获得该内存空间的地址。右值就是非左值的表达式。
// 1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <utility>
using namespace std;
class MemoryBlock
{
public:
//构造函数,申请内存资源
MemoryBlock( size_t length )
: _length( length ) , _data( new int[length] )
{
cout<<"创建对象,长度 = "<<_length<<" , 申请资源"<<endl;
}
//析构函数,释放内存资源
~MemoryBlock()
{
cout<< " 销毁对象,长度 = "<<_length<<",";
if ( _data != NULL )
{
cout<<"释放资源";
delete[] _data;
}
cout<<endl;
}
//拷贝构造函数
MemoryBlock( const MemoryBlock& other )
: _length(other._length) , _data(new int[other._length])
{
cout<<"复制构造函数,长度 = "<<other._length<<", 申请资源并复制资源到目标资源"<<endl;
//复制源对象的内存资源到目标对象的内存资源
copy( other._data, other._data + _length , _data );
}
MemoryBlock& operator = ( const MemoryBlock& other)
{
if ( this != &other )
{
cout<< "赋值操作符。长度 = "<<other._length
<<",释放已有资源。 重新申请资源并复制资源到目标资源"<<endl;
delete[] _data;
_length = other._length;
_data = new int[_length];
//复制源对象的内存资源到目标对象的内存资源
copy( other._data, other._data + _length, _data );
return *this;
}
}
size_t Length() const
{
return _length;
}
private:
size_t _length; //内存资源长度
int* _data; //对象的内存资源
};
int _tmain(int argc, _TCHAR* argv[])
{
MemoryBlock a(3);
MemoryBlock b(6);
swap( a, b );
return 0;
}
在编译时会出错:
c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(2176): error C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this
warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'。
则在stdafx.h头文件内定义了#define _SCL_SECURE_NO_WARNINGS,则编译通过。
下面为右值引用:
// 3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class MemoryBlock
{
public:
MemoryBlock( size_t length )
: _length( length ) , _data( new int[length] )
{
cout<<"创建对象,长度= "<<_length <<", 申请资源"<<endl;
}
~MemoryBlock()
{
cout<<"销毁对象,长度="<<_length<<", ";
if ( NULL != _data )
{
cout<<"释放资源";
delete[] _data;
}
cout<<endl;
}
//移动构造函数
MemoryBlock(MemoryBlock&& other)
: _length(0), _data(NULL)
{
cout<<"右值引用构造函数,长度= "<<other._length<<",将资源指向已有资源"<<endl;
_length = other._length;
_data = other._data;
other._length = 0;
other._data =NULL;
}
//移动赋值操作符“=”
MemoryBlock& operator = (MemoryBlock&& other)
{
if (this != &other)
{
cout<<"右值引用赋值操作符,长度= "<<other._length<<endl;
if ( NULL != _data )
{
cout<<",释放已有资源, "<<endl;
delete[] _data;
}
_length = other._length;
_data = other._data;
other._length = 0;
other._data =NULL;
}
return *this;
}
size_t Length() const
{
return _length;
}
private:
size_t _length;
int* _data;
};
int _tmain(int argc, _TCHAR* argv[])
{
MemoryBlock a(3);
MemoryBlock b(6);
swap( a, b );
return 0;
}