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;//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=()