- 這兩個特性是c++11里比較有性能提升意義的。個人認為這兩個特性也體現了c++對性能提升的極限追求。
- 通過改寫經典c++面試題mystring來體會
- move不能減少臨時變量的產生,但是可以減少內存的維護量
- 代碼
-
//右值引用
/*
左值對象:持久存在的對象,具有名字,可以對其去地址
右值對象:臨時對象,表達式結束后它就沒了,不能對它取地址,它也沒有名字~
右值引用類型:引用右值的類型,用&&來表示
*/
/************************************************************************/
/*使用右值引用改進MyString類,添加移動構造函數 */
/************************************************************************/
#include<iostream>
#include<vector>
usingnamespace std;
classMyString
{
public:
//普通構造函數
MyString()
{
cout <<"\n default construct\n";
mLength =0;
mData = NULL;
}
//帶參數的普通構造函數
MyString(constchar* str)
{
cout <<"\n arg construct\n";
mLength = strlen(str);
mData =newchar[mLength+1];
memcpy(mData, str, mLength);
mData[mLength]='\0';
}
//拷貝構造函數
MyString(constMyString& str)
{
cout <<"\n copy construct\n";
//深拷貝
mLength = str.mLength;
mData =newchar[mLength +1];
memcpy(mData,str.mData,mLength);
mData[mLength]='\0';
}
//移動構造函數
MyString(MyString&& str)
{
cout <<"\n move construct\n";
mLength = str.mLength;
mData = str.mData;
//
str.mLength =0;
str.mData = NULL;//這個是必須的,否則臨時對象和此對象指向同一個資源,臨時對象析構時會釋放資源導致錯誤
}
//賦值函數
MyString&operator=(constMyString& str)
{
cout <<"\n operator = \n";
if(this!=&str)
{
if(mData)
{
delete[] mData;
}
mLength = str.mLength;
mData =newchar[mLength +1];
memcpy(mData, str.mData, mLength);
mData[mLength]='\0';
}
return*this;
}
//右值賦值函數
MyString&operator=(MyString&& str)
{
cout <<"\n right ref operator = \n";
if(this!=&str)
{
if(mData)
{
delete[] mData;
}
mLength = str.mLength;
mData = str.mData;
str.mLength =0;
str.mData = NULL;
}
return*this;
}
//析構函數
~MyString()
{
cout <<"\n destruct \n";
if(mData)
{
delete[] mData;
mData = NULL;
}
}
public:
size_t mLength;
char* mData;
};
MyStringGetString()
{
MyString str("test str");
return str;
}
int main()
{
int i =0;
//i是左值,0是右值
MyString a;
MyString b("b");
//這兩個寫法,對於編譯器來說是一樣的
MyString c(b);
MyString d = c;//這個只調用拷貝構造函數,不會調用賦值函數;分兩行寫就會調用賦值,為什么會這樣。。。
MyString e =GetString();
MyString f(GetString());//調用移動構造函數
MyString h;
h =MyString();//調用右值賦值函數
MyString g;
g = e;//調用賦值函數
MyString m;
m =GetString();
vector<MyString> v;
MyString str("123");
v.push_back(str);//會創建臨時變量,調用拷貝構造函數
v.push_back(std::move(str));//調用移動構造函數,std::move將左值引用轉化為右值引用,
//push_back在接受右值引用后調用類的移動構造函數將資源移動到
//容器中,而右值引用對應的對象具體處理要參考具體移動構造函數的實現。我這里是將資源設null了。
//移動語義的使用場合
/************************************************************************/
/* 目的,通過右值和資源移動來實現臨時對象資源的所有權轉移,減少內存操作(申請拷貝釋放),對含有堆資源的對象才比較有意義,而且必須實現相應的移動構造函數 */
/************************************************************************/
}