在c++11中,支持右值引用,右值引用的用處之一是移動語義,對象的資源所有權發生轉移,在c++11之前,移動語義的缺失是c++飽受詬病的問題之一.
什麼是左值?什麼是右值?
凡有名者,皆爲左值.左值對應變量的存儲位置,右值對應變量的值本身,右值可以被賦值給左值,或者綁定到引用.
右值引用的優點?
類的右值是一個臨時對象,如果沒有被綁定到引用,在表達式結束時候,就會廢棄,在右值被廢棄之前,移走資源進行廢物利用.
被移走資源的右值在廢棄時已經成爲空殼,析構的開銷降低.
爲臨時變量續命,也就是爲右值續命,右值在表達式結束後就消亡了,如果想繼續使用右值,就會使用昂貴的拷貝構造函數
如果能夠直接使用臨時對象已經申請的資源,既能節省資源,又能節省資源申請和釋放的時間
看一個具體的例子:
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class TestString
{
private:
char *data_;
size_t len_;
void _init_data(const char *p)
{
data_ = new char[len_ + 1];
memcpy(data_, p, len_);
data_[len_] = '\0';
}
public:
TestString()
{
data_ = NULL;
len_ = 0;
}
TestString(const char *p)
{
len_ = strlen(p);
_init_data(p);
}
TestString(const TestString &str)
{
len_ = str.len_;
_init_data(str.data_);
std::cout << "Copy Structor is called! source:" << str.data_ << std::endl;
}
TestString& operator=(const TestString &str)
{
if(this != &str)
{
len_ = str.len_;
_init_data(str.data_);
}
std::cout << "Copy Assignment is called! source:" << str.data_ << std::endl;
return *this;
}
//TestString(TestString &&str)
//{
// std::cout << "Move Constructor is called! source:" << str.data_ << std::endl;
// len_ = str.len_;
// data_ = str.data_;
// str.len_ = 0;
// str.data_ = NULL;
//}
//TestString& operator=(TestString &&str)
//{
// std::cout << "Move Assignment is called! source:" << str.data_ << std::endl;
// if(this != &str)
// {
// len_ = str.len_;
// data_ = str.data_;
// str.len_ = 0;
// str.data_ = NULL;
// }
// return *this;
//}
virtual ~TestString()
{
if(data_)
{
delete []data_;
data_ = NULL;
}
}
};
int main(int argc, char *argv[])
{
TestString a;
a = TestString("Hello ");
std::vector<TestString> vec;
vec.push_back(TestString(" Wrold"));
return 0;
}
說明兩點:
(1)左值引用符號&,右值引用符號&&,右值引用符號只有在c++11中才被支持;
(2)程序中的註釋部分,包含右值引用拷貝構造函數和右值引用賦值構造函數,取消註釋前後程序的運行結果不一致,可以體會一下右值引用的含義,以及移動語義的優點: