C++11特性--右值引用,移動語義,強制移動move()
阿新 • • 發佈:2019-02-08
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=()
*右值:不能對其應用地址運算子的值。
*將右值關聯到右值引用導致該右值被儲存到特定的位置,且可以獲取該位置的地址
*右值包括字面常量(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;
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=()