右值引用
左值:赋值号左边,可以取地址
- 变量名
- 返回左值引用的函数调用
- 前置自增,前置自减:++i;–i;
- 赋值运算
- …
右值:赋值号右边,不可以取地址;将亡值,通常是将要被移动的对象
- 常量
- 返回非用类型的函数调用
- 后置自增:i ++
- 算术表达式 (a+b)
- 逻辑表达式(a && b)…
- std::move() 移动的值
- 被右值引用的值
- …
定义:
如,将func() 返回类对象赋值给类A的对象a
A && a = func();
功能:调高使用临时对象的效率
code:
分析:
发生1次构造,1次拷贝构造:
第一次构造为getObjectA()中A()的构造
1次拷贝构造为将A() 赋值给临时对象,
临时对象申请的空间赋值给对象a 没有发生拷贝行为,提高了效率
class A
{
public:
A(){
cout<<"A() "<<this<<endl;
}
~A(){
cout<<"~A() "<<this<<endl;
}
A(const A &another)
{
cout<<"A(const A&)"<<&another<<"->"<<this<<endl;
}
};
A getObjectA()
{
return A();
}
int main()
{
A && a = getObjectA();
return 0;
}
运行结果:
A()
A(const A&)
~A()
~A()
移动赋值
语义:对象赋值时,避免内存空间的重新分配
定义:
如, 将类A 对象a 移动赋值给 对象b
A b(std::move(a));
功能:提高将类对象返回值赋值给临时对象的效率
code (包含自实现类中的6大默认):
类对象的移动构造
分析:
一次构造,一次移动构造
一次构造为 a对象的构造
移动构造为 将 a 赋值给b, a所申请的空间没有进行拷贝,提高了效率
class Move
{
public:
Move(int i = 0):_i(new int(i))
{
cout<<"Move()"<<endl;
}
Move(const Move & another)
:_i(new int(*another._i))
{
cout<<" Move(const Move & another)"<<endl;
}
Move & operator=(const Move & another)
{
cout<<" Move & operator=(Move & another)"<<endl;
if(this != &another)
{
delete _i;
_i = new int(*another._i);
}
return *this;
}
Move( Move && another)
{
cout<<" Move( Move && another)"<<endl;
_i = another._i;
another._i = nullptr;
}
Move & operator=(Move && another)
{
cout<<" Move & operator=(Move && another)"<<endl;
if(this != &another)
{
delete _i;
_i = another._i;
another._i = nullptr;
}
return *this;
}
~Move()
{
if(_i != nullptr)
delete _i;
cout<<"~Move()"<<endl;
}
int *_i;
};
int main(int argc, char *argv[])
{
//拷贝构造(深拷贝),若不自实现拷贝构造,则报错
// Move m;
// Move n(m);
//拷贝赋值
// Move p;
// Move q;
// q = p;
//移动构造
Move a;
Move b(std::move(a)); //std::move() 将左值变为右值,m为将亡值
// 移动赋值
// Move c;
// Move d;
// d =(std::move)(c);
return 0;
}
运行结果:
Move()
Move( Move && another)
~Move()
~Move()
类成员对象的移动构造
分析:
若要实现类Moveable 成员对象Complex _c的移动构造,需要在类Moveable的构造函数中使用std::move移动_c对象,可以避免类Moveable的对象赋值时,类成员对象_c所申请空间的拷贝,提高了效率
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(int f = 0)
:_f(new float(f))
{
cout<<"Complex()"<<endl;
}
Complex(const Complex & another)
:_f(new float(*another._f))
{
cout<<"Complex(const Complex & another)"<<endl;
}
Complex(Complex && another)
:_f(another._f)
{
another._f = nullptr;
cout<<" Complex(Complex && another)"<<endl;
}
Complex& operator = (const Complex & another)
{
cout<<"Complex& operator = (const Complex & another)"<<endl;
if(this != &another)
{
delete _f;
_f = new float;
*_f = *another._f;
}
return *this;
}
Complex& operator = ( Complex && another)
{
cout<<" Complex& operator = (const Complex && another)"<<endl;
if(this != &another)
{
delete _f;
_f = another._f;
}
return *this;
}
~Complex()
{
if(_f != nullptr)
delete _f;
}
float *_f;
};
class Moveable
{
public:
Moveable(int i)
:_i(new int(100)),_c(2.1) //先父类,再类对象,再本类
{
cout<<" Moveable(int i)"<<endl;
}
Moveable(const Moveable &another )
:_i(new int(*another._i))
,_c(another._c)
{
cout<<" Moveable(const Moveable &another )"<<endl;
}
Moveable(Moveable &&another)
{
cout<<" Moveable(Moveable &&another)"<<endl;
_i = another._i;
another._i = nullptr;
_c = std::move(another._c); //走 Complex 移动赋值
}
~Moveable()
{
if(_i != nullptr)
delete _i;
}
int *_i;
Complex _c; //类对象成员
};
int main(int argc, char *argv[])
{
Moveable m(100);
Moveable n(std::move(m)); //走移动构造
return 0;
}
运行结果:
Complex()
Moveable(int i)
Complex()
Moveable(Moveable &&another)
Complex& operator = (const Complex && another)