C++11 右值,右值引用,移动构造,移动赋值

您所在的位置:网站首页 c赋值构造函数 C++11 右值,右值引用,移动构造,移动赋值

C++11 右值,右值引用,移动构造,移动赋值

2022-11-29 05:11| 来源: 网络整理| 查看: 265

目录

一、左值,左值引用,右值,右值引用的相关概念:

1. 什么是左值,什么是左值引用?

2. 什么是右值,什么是右值引用?

3. 右值的属性是右值,右值引用的属性是左值

4. 左值引用与右值引用的简单比较:

二、右值引用的作用(使用场景)

左值引用的作用:

左值引用的短板:

右值引用作用1,使用场景1:

to_string传值返回,string类的拷贝构造 vs 移动构造

to_string传值返回,string类的拷贝赋值 vs 移动赋值

场景一总结:

右值引用作用2,使用场景2:

三、模板中的万能引用&&  与  完美转发

一、左值,左值引用,右值,右值引用的相关概念: 1. 什么是左值,什么是左值引用?

左值是一个表示数据的表达式(如变量名或解引用的指针),左值的特征是可以获取它的地址 + 可以对它赋值,左值可以出现在赋值符号的左边。(右值不能出现在赋值符号的左边)。 有一个例外:const修饰的左值不能出现在赋值符号左边。故,左值最大的特点是是:可以对它取地址。

左值引用就是对左值的引用,给左值取别名。

// 以下的p,b,c,*p都是左值 int* p = new int(0); int b = 1; const int c = 2; *p = 10; // 左值引用: int*& rp = p; int& rb = b; const int& rc = c; int& ri = *p; 2. 什么是右值,什么是右值引用?

右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引 用返回,也就是必须是值返回)... 右值不能出现在赋值符号的左边,可以出现在赋值符号的右边,右值不能取地址。 右值引用就是对右值的引用,给右值取别名。 赋值运算符的左侧必须为左值。“=”: 左操作数必须为左值。

右值可以分为两种:1. 内置类型右值-纯右值    2. 自定义类型右值-将亡值

double x = 10.1, y = 20.2; // 右值示例: 10; x+y; fmin(x, y); // 值返回 // 右值引用示例: int&& ri = 10; double&& rd = x + y; double&& rd2 = fmin(x, y); 3. 右值的属性是右值,右值引用的属性是左值

右值不能取地址,比如10不能取地址。但是右值引用可以取地址,且可以给右值引用赋值。也就是 int&& ri = 10; &ri; ri = 20;  是合法的。因为给右值取别名后,会导致右值引用被存储在特定位置,属性变为左值。

右值引用的属性是左值。const 右值引用的属性是const 左值。因为左值可以取地址,可以赋值。因此右值引用可以取地址,可以赋值。const 右值引用可以取地址,不能赋值。

4. 左值引用与右值引用的简单比较:

1. 左值引用只能引用左值,不能引用右值。 const 左值引用既能引用左值,也能引用右值。

2. 右值引用只能引用右值,不能引用左值。 但是右值引用可以引用move后的左值。(这个其实就是move函数的作用,std::move函数可以将左值强制转化为右值引用,返回这个左值的右值引用)

二、右值引用的作用(使用场景)

既然左值引用可以引用左值,且const 左值引用还可以引用右值,那么右值引用的作用是什么呢?探究C++11引入右值引用的作用之前,先来探究左值引用的作用,以及左值引用的短板,从而理解右值引用的作用。

左值引用的作用:

1. 左值引用做函数参数。

a. 引用传参,减少拷贝,提高效率。最典型的比如拷贝构造函数,operator=(),以对象为模板拷贝构造一个新的对象,这里传引用可以减少传参时的拷贝,提高效率。 b. 做输出型参数,代替C语言的传指针。

2. 左值引用做函数返回值。

a. 传引用做返回值,减少拷贝,提高效率。(我们知道,传值返回是要拷贝构造一个临时对象的(编译器不优化或不能优化的情况下),这里会降低效率。) b. 传引用返回,用于修改返回对象。最典型的比如 vector的operator[]。很多堆区开辟的对象,都可以采用传引用返回的方式,使程序使用对一个对象进行处理。

重新审视拷贝构造函数和重载赋值运算符函数的参数,为什么要定为 const Type& t   一方面,传引用可以提高效率,减少拷贝。这里加const的作用可以防止修改左值引用。另一方面是,const 左值引用才能引用右值。否则这个拷贝构造函数或operator=不能以右值为实参。也就是 T t(T());  将报错,因为左值引用不能引用临时对象的这种右值。

左值引用的短板:

若一个对象在堆区,则函数可以传引用返回。但是,对于函数内的局部临时对象,函数返回后,出了作用域,局部对象就会销毁,是不可以传引用返回的。 而如果采用值返回,则会发生拷贝构造,若这个对象不是内置类型,而是深拷贝的自定义类型,则发生深拷贝还会降低效率。 对于自定义类型的右值,我们称之为将亡值,也就是函数内的局部临时对象。

右值引用作用1,使用场景1:

C++11中,右值引用的一个重要功能,就是解决函数值返回涉及深拷贝的局部临时对象的低效率问题。解决方法为:利用右值引用为自定义类型实现移动构造和移动赋值成员函数。

to_string传值返回,string类的拷贝构造 vs 移动构造

比如,我们模拟实现一个string类。则,yzl::string to_string(int val); 函数,用于将整型转为我们实现的string类型,此处必须传值返回,因为函数内创建的局部string对象出了函数作用域就会销毁。

yzl::string to_string(int val) { yzl::string str; // ... return str; // 此str的属性为右值 } void func() { yzl::string s = yzl::to_string(10); } // 以模拟实现string类为例的移动构造和移动赋值实现。 // 移动构造 string(string &&s) : _str(nullptr), _size(0), _capacity(0) { cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3