C++11:右值引用和转移赋值
1.首先认识左值和右值的定义:
左值:表达式可以引用到一个对象,并且这个对象是一块内存空间并可以检测和存储,这个表示即是左值。
右值:直接引用了一个存储在内存地址中的数据。
右值最大限度只能被一个常量引用:
const int &a = 1;
规则:临时变量是右值,且可以改变:
T().set().get()
T为临时变量,set()设置新值,get()获取更改后的值。
2.首先写一个MyString类:
#include<vector> class MyString { private: int _len; char* _data; void init_data(const char* str) { _data = new char[_len+1]; memcpy(_data,str,_len); _data[_len] = '\0'; } public: MyString() { _len = 0; _data = NULL; } MyString(const char* str) { _len = strlen(str); init_data(str); } MyString(const MyString& rhs) { _len = rhs._len; init_data(rhs._data); } MyString& operator=(MyString& rhs) { if(this != &rhs) { _len = rhs._len; init_data(rhs._data); //MyString(rhs); } return *this; } virtual ~MyString() { if(_data) free(_data); } }; int main() { Mystring a; a = MyString("Hello"); std::vector<MyString> vec; vec.push_back(MyString("World")); }
左值和右值引用符号区别:
void print_value(int& a) { std::cout << "LValue" << endl; } void print_value(int&& a) { std::cout << "RValue" << endl; }
右值引用实际是用来支持转移赋值和转移构造:
MyString(MyString&& rhs) //不包含const { _len = rhs._len; _data = rhs._data; rhs._len = 0; rhs._data = NULL; } MyString& operator(MyString&& rhs) //不包含 const { if(this != &rhs) { _len = rhs._len; _data = rhs._data; rhs._len = 0; rhs._data = NULL; } return *this; }
转移构造和赋值的好处是:节省了资源,提高了程序效率。
std::move是标准库提供的将一个命名对象转换为一个临时对象(右值)来支持转移构造和赋值:
template <class T> void swap(T& a, T& b) { T c(std::move(a)); a=std::move(b); b=std::move(c); } template <class T, size_t N> void swap(T (&a)[N], T(&b)[N]) { for(size_t i = 0; i<N; ++i) swap(a[i], b[i]); }
这样提高了swap效率。
文章出自:http://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/index.html