C++移动构造函数和移动赋值函数

在移动构造函数和移动赋值函数之前,我们已经知道了拷贝构造函数(将对象当作参数传入,在函数体内进行浅拷贝或者深拷贝以完成数据的拷贝复制)和赋值函数(重载运算符,操作和拷贝构造函数差不多)

这里引入右值的概念,和先前左值是相对应的

右值和左值

左值:指表达式结束后依然存在的持久化对象,有名字的对象都是左值

右值:表达式结束就不再存在的临时对象,右值没有名字

除了有无名字这个判断方法外,还有一种方法是看能否对表达式取地址,如果能,则为左值,否则为右值

右值又细分为将亡值和纯右值

将亡值:1.非引用返回的临时变量;2.运算表达式产生的结果;3.字面常量(C风格字符串除外,它是地址)

纯右值:与右值引用相关的表达式

举例:     int a=7;//a为左值,7为右值

             A a=cmp();//cmp()返回一个A类临时变量,a为左值,cmp()为右值

之前我们学过左值引用(为左值取别名),右值引用也是同样的道理

左值引用和右值引用

左值引用:数据类型& 变量名=左值;

右值引用:数据类型&& 变量名=右值;

举例:int &&a=8;//为右值8取别名为a,a是一个左值

右值引用使得一些将亡值重获新生,延长了其生命周期

左值引用只能绑定左值(除常量左值引用外),右值引用只能绑定右值

常量左值引用可以绑定非常量左值,常量左值和右值

如:const int&a=7;//注意常量左值引用的右值不能修改

引入右值引用的原因是为了实现移动语义

移动语义是转移对象资源的操作,拷贝语义是将对象资源进行拷贝复制的操作

移动语义

移动构造函数:类名(类名&& 源对象){......}//与拷贝构造函数相对应

移动赋值函数:类名& operator=(类名&& 源对象){……}//与赋值函数相对应

参数是右值则调用移动构造函数,是左值则调用拷贝构造函数,如果想让左值调用移动构造函数,可以使用move()方法将左值强制转换为右值,move()函数返回左值的右值形式,左值的资源所属不会发生改变

如没有移动构造函数/移动赋值函数,则会调用拷贝构造函数/赋值函数(条件满足,移动优先)

 如果出现函数嵌套的情况时可能会出现错误:

void fun1(int&ii);
void fun1(int&&ii);
void fun2(int i)
{
    fun1(i)        
}
int main()
{
    fun2(8);
}

当你想通过fun2调用fun1的右值版本时,却调用了左值版本,这就是不完美的转发

完美转发

完美转发是指函数不仅能准确地转发参数的值,还能保证被转发参数的左、右值属性不变

 C++11提供了以下方案:

1.如果模板中(包括类模板和函数模板)函数的参数书写成为T&& 参数名,那么,函数既可以接受左值引用,也可以接受右值引用//普通函数不可行

2.提供了模板函数std::forward<T>(参数) ,用于转发参数,如果 参数是一个右值,转发之后仍是右值引用;如果参数是一个左值,转发之后仍是左值引用

例:

template<typename TT>
void func2(TT&& ii)
{

    func1(forward<TT>(ii));

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值