1. 程式人生 > >新特性(3)---move語義

新特性(3)---move語義

move語義

左值和右值

在說move語義之前,不得不說的是左值和右值。
通俗簡單點的講左值和右值通過是否在記憶體中有空間來分類。左值是在記憶體空間實體如(變數和函式等),而相反的沒有空間的為右值如臨時物件。

	int a=1;//a為左值,1為右值
	int *p = &a;//p為左值
	int f = test();//test()返回一個臨時物件,為右值

再比如這樣,test()返回一個全域性變數是一個左值

int t;
int & test()
{
      return  t;
}

test()=5;

左值引用

顧名思義,左值引用又分為常量左值引用和非常量左值引用,區別 在於使用了const是否能改變。

int b;
int &a=b;//常量左值引用
const int &c=b;//非常量左值引用

非常量左值引用只能引用非常量左值,如

int a;//非常量左值
const int b;//常量左值
int &c=a//ok,引用非常量左值
int &c=b;//error,引用常量左值,造成了常量變為可修改
int &c=123//error,引用右值,表示式結束臨時物件已銷燬。

常量左值引用可以引用所有左值和右值

const int &c=a;.......

右值引用

當然左值引用是有一定侷限的,如常量左值引用的右值永遠只能是常量。如果我們想獲得非常量右值該怎麼辦呢。這時候c++11增加了新的引用型別 T&& t,來進行右值引用。
右值引用也分為常量右值引用和非常量右值引用,右值引用都不能用來引用左值。常量右值引用可以引用常量右值和非常量右值。而非常量右值引用只能引用非常量右值。

	const int  && a = 123;

move語義

語義

在說move語義只前先介紹下什麼叫語義
語法 = 某個原始碼怎麼寫
語義 = 這個原始碼怎麼執行
什麼意思呢,就如泛型和正常程式碼的區別,泛型程式設計只會告訴你這個原始碼怎麼執行,在你確定型別後才是某個原始碼怎麼寫。

賦值語義

在變數中經常用到賦值語義,賦值語義會先拷貝出一個臨時變數,再將臨時變數拷貝給左邊的變數。在函式返回值中也是先產生臨時變數再拷貝,這樣每次賦值都會產生一次臨時變數,當賦值複雜,如字串,容器等將產生許多臨時變數,降低效率。
如下,是賦值語義的兩個語法:

int
b=a[1]; int b=*(a+1);

move語義

所以為解決產生多餘臨時變數的問題,c++11中就出現了move語義,move語義就是把舊指標的值複製到新指標,並把舊指標的值賦為NULL。如果我們能確定某個值是一個非常量右值,則我們在進行臨時物件的拷貝時,可以不用拷貝實際的資料,而只是“竊取”指向實際資料的指標,並將臨時物件的生命週期提高,避免析構。(而我們之前提到的右值引用就是move語義提供的語法支援)
std::move 會傳入一個 T&&的值,不用進行拷貝,但move後的變數仍然有效,但狀態不明

string str1{"hello"};
string str2{"hello word "};
str1=std::move(str1);