烟台学校网站建设,wordpress 文件,传媒公司产品宣传片,企业网站打包下载左值引用与右值引用的区别#xff1f;右值引用的意义#xff1f; 1 区别1.1 功能差异1.2 左值引用1.3 右值引用1.3.1 实现移动语义1.3.2 实现完美转发 2 引用的作用3 区分左值和右值3.1 左值3.2 右值 1 区别
左值引用是对左值的引用#xff1b;右值引用是对右值的引用。
右值引用的意义 1 区别1.1 功能差异1.2 左值引用1.3 右值引用1.3.1 实现移动语义1.3.2 实现完美转发 2 引用的作用3 区分左值和右值3.1 左值3.2 右值 1 区别
左值引用是对左值的引用右值引用是对右值的引用。
1使左值指向右值 const 左值引用能指向右值局限是不能修改这个值。 注意使用const不能修改值时可以使用引用引用该值并对其进行修改。
2使右值指向左值 右值引用通过**std::move(v)**可以将左值转化为右值此时右值就是将亡值。 3声明出来的左值引用或右值引用都是左值
int i0;//引用是必须初始化
//此时的j引用的是右值100
int j100; //右值引用 int ki;//左值引用1.1 功能差异
1.2 左值引用
避免对象拷贝。
函数传参函数返回值
1.3 右值引用
1.3.1 实现移动语义
解决对象赋值的问题避免资源堆上的重新分配。有深拷贝的情况下。 以数据库举例。 以前与数据库创建连接不想把连接对象关闭需要再创建另一个连接再把连接资源拿过来。 现在直接把连接对象的资源拿给另一个对象是用就不用再创建并删除一个与数据库之间的连接对象。 以文件举例。 以前一个文件描述fd按照以前的深拷贝需要重新打开一个文件。 现在直接把该文件资源fd移动到另外一个对象中就可以了。 拷贝赋值构造与拷贝构造
//拷贝赋值构造 深拷贝资源的重新分配
A a1,b1;
a1b1; //拷贝构造 深拷贝
A a2;
A b2(a2);//当前a2是左值
coutb,pb.pendl;//输出结果b,pA(const A)...A b2(std::move(a2));//改为右值
coutb,pb.pendl;//输出结果b,pA(A)...深拷贝与浅拷贝
//深拷贝
A(const Aa)//拷贝构造
{//拷贝构造中使用的是const只能读不能写所以不能再拷贝构造中使用移动构造进行资源转移pnew int(10);memcpy(p,a.p,10*sizeof(int));//重新分配内存coutA(const A):ppendl;
}//浅拷贝
A(A a) //移动构造
{//直接把a上的资源赋值给自己并把a中的资源置空this-pa.p;a.pnullptr;coutA(A)endl;
}stl中的应用
listA alist;
alist.push_back(A());//当前A()为右值
auto elealist.front();//取出第一个值
coutele.pele.pendl;//输出结果ele.pA(A)...1.3.2 实现完美转发 定义函数模板可以将自己的参数完美地转发给内部调用的其他函数。 完美指的是不仅能准确地转发参数的值还能保证转发的参数的左右值属性不变。使用std::forward(v)实现。 //左值
void func(int n)
{coutleft valuenendl;
}//右值
void func(int n)
{coutright valuenendl;
}//调用函数进行转发//c11以前
templatetemplate T
void revoke(T t)
{//此时的t唯一个具体的值func(t);//只能转发左值调用的函数为func(int n)
}//c11以前如果一定要转发右值
void revoke(const T t)
{func(t);//但是不能对t进行修改
}/**************分割线***************///c11 完美转发
templatetemplate T
void revoke(T t)//T t为万能引用
{func(std::forwardT(t));
}万能引用具有模板参数或者模板推导的叫做万能引用。
1具有模板参数
templatetypename T
void tempFun(T t) {} //模板类型的这种用法 T 是万能引用最常见的使用场合2具有模板推导
auto var2 var1; //auto这种需要推断类型的地方万能引用虽然跟右值引用的形式一样但右值引用需要是确定的类型如: int ref x;就是右值引用。
借用万能引用的方式接受左右属性的值。使用引用折叠规则实现。
templatetemplate T
void revoke(T t)//T t为万能引用
{func(std::forwardT(t));
}int main()
{int i10;revoke(10);//右值 万能引用中会转换成int trevoke(i);//左值 万能引用中会转换成int treturn 0;
}引用折叠规则
1参数为左值或左值引用T将转化为int
2参数为右值或右值引用T将转化为int
注意万能引用只接收值void revoke(T t)中的t仍然是左值
std::forward(v):
1T为左值引用v将转化为T类型的左值。
2T为右值引用v将转化为T类型的右值。
int main()
{int i10;int mi;int n100;//不使用类型强制转换会直接到调用左值void func(int n)remoke(m);remoke(n);//使用类型强制转换remoke(static_castint(m));remoke(static_castint(n));return 0;
}2 引用的作用
1别名没有地址
2声明时必须要初始化
3通过引用修改变量值
3 区分左值和右值
3.1 左值
可以在等号左边能够取地址具名
举例
1变量名
2返回左值引用的函数调用
3前置自增/自减
int i0;
i10;//i为左值
coutiendl; //输出结果104赋值运算/复合赋值运算
int i0;
//赋值运算
(i9)100;
coutiendl;//输出结果100//复合赋值运算
(i10)1000;
coutiendl;//输出结果10005解引用
A *anew A;
*a...6…
3.2 右值
只能在等号右边不能取地址不具名 纯右值 举例 1字面值 2返回非引用类型和函数调用 3后置自增/自减 int a0;
i100;//error 纯右值不能作为左值
i;//正确写法4算术表达式*/ 5逻辑表达式^|~ 6比较表达式 7… 将亡值c11新引入的与右值引用移动语义相关的值类型 定义将亡值用来触发移动构造或移动赋值构造并进行资源转移之后将调用析构函数