1. 程式人生 > >C++11特性--右值引用,移動語義,強制移動move()

C++11特性--右值引用,移動語義,強制移動move()

1.右值引用
  *右值:不能對其應用地址運算子的值。
  *將右值關聯到右值引用導致該右值被儲存到特定的位置,且可以獲取該位置的地址
  *右值包括字面常量(C風格字串除外,它表示地址),諸如X+Y等表示式以及返回值得函式(條件是該函式返回的不是引用)
  *引入右值引用的主要目的之一是實行移動語義
  Example:
 int f(int x,int y)
{
return x+y;
}
int main()
{

int a=1;
int b=2;
int &&rab=a+b;
//rab關聯的是a+b計算的結果,即使以後修改了a,b的值也不會影響到rab 
cout<<"rab: "<<rab<<endl;
//rab: 3
a=2;
cout<<"rab: "<<rab<<endl;//rab: 3
cout<<"&rab: "<<&rab<<endl<<endl;//&rab 0x22fe30

int &&rf=f(a,b);
cout<<rf<<endl;//4


return 0;
}






2.移動語義和右值引用
  *移動語義實際上避免了移動原始資料,而只是修改了記錄。
  *要實現移動語義,需要採取某種方式,如移動建構函式(它使用右值引用作為引數,該引用關聯到右值實參),移動賦值運算子
  *移動建構函式可能修改其實參,這意味著右值引用引數不應是const
   
   Tips:實現移動語義的關鍵在於,採取某種方式(移動建構函式,移動賦值運算子),並非真正地移動資料,而只是轉交所有權(複製地址)



  Example:
  class mymove
{
private:
 int n;
 char *pt;
public:
       mymove(char ch,int m):n(m)
//建立包含i個ch的字元陣列 
{
pt=new char[m];
for(int i=0;i<m;i++ ) 
{
pt[i]=ch;
}
}

 mymove(mymove& other) //複製建構函式 
 {

n=other.n;
pt=new char[other.n];
for(int i=0;i<n;i++)
{
pt[i]=other.pt[i];


 }

 mymove(mymove&& other)
//移動複製建構函式 
 {
n=other.n;
pt=other.pt;
other.pt=nullptr;
other.n=0;
cout<<"move constructor call"<<endl;
 }

mymove& operator=(mymove&& other) //移動賦值操作符 
{
 delete [] pt;
 n=other.n;
 pt=other.pt;
 other.pt=nullptr;
 other.n=0;

 cout<<"move assignment operator call"<<endl;
 return *this;
}

mymove operator+(mymove& other)
{
mymove tem(*this);

delete [] pt;
pt=new char[n+other.n];
for(int i=0;i<n;i++) //複製tem.pt中的資料 
{
pt[i]=tem.pt[0];


for(int j=0;j<other.n;j++)//複製other.pt中的資料 
{
pt[n+j]=other.pt[j];
}

n=other.n+tem.n;
cout<<"operator+()"<<endl; 

return *this;
}

void print()   //列印mymove.pt中的資料 
{
 for(int i=0;i<n;i++)
 {
cout<<pt[i]<<ends; 
 } 
}
};


int main()
{
mymove a('a',1);
a.print();//a
cout<<endl;

mymove b('b',2);
b.print();//b b
cout<<endl;

mymove c(a+b);
c.print(); // a b b
cout<<endl;

a=b+c;
a.print();// b b a b b
cout<<endl;
return 0;
}






3. 強制移動move()
   *標頭檔案#include<utility>
   *如果類定義了移動賦值運算子,則強制使用移動賦值運算子


   Example:
  class mymove
{
  public:
  mymove& operator=(mymove& other)
  {
  cout<<"operator=()"<<endl;
  }
   
   mymove& operator=(mymove&& other)
  {
  cout<<"move operator=()"<<endl;
  }
};


int main()
{
mymove a,b;
    a=b;
    cout<<endl;
    
    a=move(b);
    cout<<endl;
return 0;
}


output:
  operator=()
  move operator=()