C++11 右值引用的使用场景分析

 更新时间:2025年06月09日 10:54:09   作者:unlockjy  
c++11中新增了右值引用的语法,本文主要说明左值引用和右值引用的使用场景,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

前言

c++11中新增了右值引用的语法,本章主要说明左值引用和右值引用的使用场景

在我们了解左值引用和右值引用前,我们要先来理解一下左值和右值分别是什么

1.左值and右值

左值是一个表示数据的表达式,我们可以获取它的地址,有持久状态存储在内存当中,变量名,指针等,只要是可以取到地址的表达式都是左值

右值也是一个数据表达式,一般是字面常量或者创建的临时对象

核心区别:是否可以拿到地址,可以取地址就是左值 取不到地址就是右值

 2.左值引用and右值引用

我们知道引用其实就是起了一个别名 左值引用和右值引用也就是起别名

一个& 就是左值引用 两个&&就是右值引用

注意:左值引用不能直接引用右值 const左值可以引用右值

右值引用不能直接引用左值 右值引用可以引用move(左值)

move是一个函数 底层我们可以理解就是将左值强转成右值 但它的属性还是左值

引用可以延长生命周期

我们知道临时变量的生命周期很短,只有执行的那一行代码

const左值可以延长生命周期 右值引用可以延长生命周期

但是普通左值引用不可以延长生命周期,这是因为临时对象是右值,普通左值引用绑定右值,就可能会出现对已经销毁的对象做无效引用

注意:这里的延长生命周期是只在当前的栈帧有效,一旦函数运行完毕,进行释放,被延长的生命周期的临时对象也就被销毁了,延长的生命周期只在当前的作用域有效!!!!

3.参数匹配

c++98当我们实现一个const左值引用作为参数,那么传左值和右值都可以

c++11新增了右值引用,当我们进行传参,编译器就会找到相对最匹配的函数继续传参!!

右值引用变量在用于表达式的时候属性是左值

4.左值引用和右值引用的使用场景

左值引用的使用场景:

当函数的参数是左值引用 可以减少拷贝 因为它只是一个别名 左值引用传返回值得到时候 也可以减少拷贝 也可以修改实参 左值引用可以解决大量的拷贝效率问题 但是有些场景不能使用传左值引用返回

我们来举个例子  就是如果在当前栈帧中创建临时对象,我们就需要传值返回,这种消耗是很大的!

在c++11 右值引用还没有出来时,编译器对此进行了优化,不同的编译器优化可能不同

我们来看一下编译器优化 虽然说最终优化只有一次构造 但是还是有构造 会造成资源消耗

还有一种情况 拷贝构造+拷贝赋值

针对于以上的这种情况 我们使用C++11的右值使用就可以很好的解决这个问题

5.移动构造和移动赋值

移动构造类似拷贝构造,移动构造函数的第一个参数必须是该类类型的右值引用

这个构造不同于拷贝构造,拷贝构造会进行深拷贝,移动构造是资源进行转移!!不会进行深拷贝

// 移动构造
string(string&& s)
{
cout << "string(string&& s) -- 移动构造" << endl;
swap(s);
}

就上述场景来看,无论编译器怎么优化,最终还是有一次拷贝,但c++11引入了右值引用,就可以很好的解决这个问题,这里的swap就是进行资源转移

移动赋值是赋值运算符重载 移动赋值函数要求第一个参数必须是该类型的右值引用

它的本质也是进行资源转移 并不会进行深拷贝,这样就可以减少深拷贝 提高资源利用效率

/// 移动赋值
string& operator=(string&& s)
{
    cout << "string& operator=(string&& s) -- 移动赋值" << endl;
    swap(s);
    return *this;
}

6.引用折叠and万能引用

C++11中不可以直接将左值引用和右值引用写在一起 int& && x = i; 这种写法是错误的

我们需要通过模版或者typedef的操作 构成引用的引用

C++11规定 右值引用的右值引用折叠后是右值引用 其他的组合折叠后都是左值引用

我们通过一些例子来理解一下:

万能引用其实就是一个模版 将参数设计成T&& 既可以接受左值引用又可以接受右值引用

template<class T>
void Function(T&& t)
{
    Fun(t);
}

7.完美转发

完美转发的核心要点就是保持当前对象的属性

template<class T>
void Function(T&& t)
{
    //Fun(t);
    Fun(forward<T>(t));
}

完美转发的使用场景:我们知道变量表达式都是左值属性 当一个右值被右值引用绑定后 右值引用变量表达式的属性是左值 Function的t的属性是左值 将t传给Fun,那么只会匹配左值引用的Fun函数,代码结果就会出现错误 这个时候我们就需要使用完美转发保持t的属性 

完美转发forward的本质是一个函数模版,核心是通过引用折叠实现 如果说传给Function的实参是右值 T被推导int,不进行折叠,forward内部t被转换成右值引用进行返回 如果说传给Function的实参是左值,T被推导int&,引用折叠左值引用,forward内部t被强转为左值引用返回

到此这篇关于C++11 右值引用的文章就介绍到这了,更多相关C++11 右值引用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言入门之浮点数

    C语言入门之浮点数

    这篇文章主要为大家介绍了C语言的浮点数,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • C++实现对象化的矩阵相乘小程序

    C++实现对象化的矩阵相乘小程序

    这篇文章主要为大家详细介绍了C++实现对象化的矩阵相乘小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • C++实现广度优先搜索实例

    C++实现广度优先搜索实例

    这篇文章主要介绍了C++实现广度优先搜索,对于C++程序员来说非常有借鉴价值,需要的朋友可以参考下
    2014-08-08
  • c语言中abs()和fabs()的区别点整理

    c语言中abs()和fabs()的区别点整理

    在本篇文章里小编给大家分享的是关于c语言abs()和fabs()的区别,有需要的朋友们可以参考学习下。
    2020-02-02
  • opencv实现角点检测

    opencv实现角点检测

    这篇文章主要为大家详细介绍了opencv实现角点检测,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言程序设计之指针的应用详解

    C语言程序设计之指针的应用详解

    为了让大家能够更准确的了解C语言中指针的使用,本文为大家准备了四个指针相关的例题,文中的示例代码讲解详细,感兴趣的小伙伴可以学习一下
    2022-11-11
  • C语言数据结构之扩展字符详解

    C语言数据结构之扩展字符详解

    掌握C语言数据结构的关键在于理解其核心概念,扩展字符作为其中的重要一环,对于编程人员来说至关重要,本指南将为您深入剖析扩展字符的相关知识,带您轻松掌握C语言数据结构,让我们一起探索这个令人着迷的领域吧!
    2024-03-03
  • c++虚函数与虚函数表原理

    c++虚函数与虚函数表原理

    这篇文章主要介绍了c++虚函数与虚函数表原理,用virtual 修饰的成员函数叫虚函数,下面围绕c++虚函数与虚函数得相关资料展开内容,需要的朋友可以参考一下
    2021-12-12
  • C语言实现跨文件传输数据的几种方式

    C语言实现跨文件传输数据的几种方式

    C语言是一种强大的、通用的编程语言,常用于系统级编程,包括硬件交互,如中断处理和数据采集,在本文中,我们将深入探讨如何使用C语言进行跨文件数据传输,文中有相关的代码供大家参考,需要的朋友可以参考下
    2024-08-08
  • C语言编程数据结构的栈和队列

    C语言编程数据结构的栈和队列

    本篇文章是C语言编程篇,主要为大家介绍C语言编程中的数据结构,详细的讲解了数据结构的栈和队列有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09

最新评论