主页 > 软件开发  > 

左值引用与右值引用

左值引用与右值引用
一、左值引用与右值引用的区别

1.左值引用是对左值的引用;右值引用是对右值的引用(不过也有特例)

const左值引用能指向右值,不过不能修改;右值引用通过std::move(v)可以指向左值

声明出来的左值引用或者右值引用都是左值(int& lref = n, int&& rref = 20, lref和rref都是左值)

2.左值引用与右值引用在功能上的差异

(1)左值引用:左值引用用来传参或者做函数返回值可以避免对象的拷贝

(2)右值引用:实现移动语义和完美转发

①移动语义:通过实现移动语义,对象赋值时,避免资源的重新分配(移动构造和移动赋值构造)

②完美转发:函数模版可以将自己的参数完美地转发给内部调用的其他函数

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

// 接受左值引用的函数 void func(int &n) { std::cout << "lvalue=" << n << std::endl; } // 接受右值引用的函数 void func(int &&n) { std::cout << "rvalue=" << n << std::endl; } // 模板函数,使用std::forward完美转发 template<typename T> void revoke(T &&t) { // 函数模版的参数 -完美交给-> 内部的函数 // 参数的值 + 参数的左右值属性 func(std::forward<T>(t)); } int main() { int num = 10; revoke(num); // 传入左值 lvalue=10 revoke(20); // 传入右值 rvalue=20 return 0; }

借助T&&实现转发语义,引入了引用折叠规则:参数为左值或左值引用,T&&将转化为A&;参数为右值或右值引用,T&&将转化为A&&

std::forward<T>(v) T为左值引用类型,v将转化为 T类型的左值;T为右值引用类型,v将转化为 T类型的右值

二、区分左值和右值

1.左值:可以在等号左边,能够取地址,具名(下面举一些例子)

变量名、前置自增和自减(++i,--i)、解引用表达式

返回左值引用的函数调用

// 定义一个函数,返回vector<int>中指定位置元素的左值引用 std::vector<int>& getElement(std::vector<int>& vec, size_t index) { return vec[index]; } std::vector<int> numbers = {1, 2, 3, 4, 5}; // 调用函数获取左值引用 // getElement(numbers, 2)这个函数调用就是左值 int& ref = getElement(numbers, 2);

赋值运算或复合赋值运算符表达式

// (i = 9)是左值 (i = 9) = 1000; std::cout << "i:" << i << std::endl; // i:1000 // (i += 20)是左值 (i += 20) = 10000; std::cout << "i:" << i << std::endl; // i:10000

2.右值:只能在等号右边,不能取地址,不具名;右值分为两大类,纯右值和将亡值

(1)纯右值:字面值、返回非引用类型的函数调用、后置自增和自减

算术表达式[a+b]、逻辑表达式[a&&b]、比较表达式[a==b, a >= b]

(2)将亡值:C++11新引入的与右值引用[移动语义]相关的值类型

将亡值用来触发移动构造或移动赋值构造,进行资源转移,之后将亡值将调用析构

std::move static_cast<T&&>(x) 可以将左值转化为将亡值(将左值转换为右值、使拷贝变为移动)

标签:

左值引用与右值引用由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“左值引用与右值引用