C++11(二) 革新:引用折叠与lambda表达式

前言

接上一篇C++11博客的内容,继续编写

移动构造和移动赋值

左值会走上面这个

右值会走下面这个

这里只有鉴定你的属性是左值,才能移动你右值引用里面的资源

移动构造和移动赋值与拷贝构造和拷贝赋值的核心区别:

只有进行深拷贝的类才考虑移动构造和移动赋值

左值在这里就得老老实实地拷贝,因为都是一些持续存在的值

右值都是一些即将销毁的值(临时对象,匿名对象等),里面的成员不能进行修改,就可以将资源进行掠夺

右值引用的属性是左值

左值引用是直接起作用,传值传参要拷贝,传值返回要拷贝,传引用传参,传引用返回不用拷贝,因为返回的是别名,形参是实参的别名

右值引用是依靠移动语义(移动构造,移动赋值)来起作用,他把右值引用给区分出来,当你要进行右值拷贝的时候,移动其资源

不管怎么样,只要我们写了移动构造和移动赋值,传值返回,直接接收和先定义对象再接收,都没有多大区别,这才是保障

这里使用右值引用会更高效

这里就说明提效了,左值插入拷贝构造代价更高,右值移动构造的代价更低

引用折叠

后来的语法喜欢用using去替代typedef

引用折叠

只要有一个左值引用都是左值引用

函数模板的特点是:实参传给形参去推出T的类型,这里推成左右值都可以折叠

只要我写了T&,不管怎么样都是左值引用

传左值是左值引用,传右值是右值引用

这里是万能引用

传左值就是左值,传右值就是右值

只要是右值,都没有折叠,就只是int

传的是左值就是左值引用

完美转发

这个不是万能引用

因为是类模板的一个成员函数,这个T不是通过实参传形参推的,而是类模板实例化的时候就实例化的

所以就出现了完美转发forward,底层的核心原理还是强制类型转换,但是与move不同,move只能转成右值

如下图,函数中需要将t值再调用一遍的,如果不加入完美转发,就会都是左值属性,因为不管是左值引用还是右值引用,值的本身都是左值属性,打印出来的就全是左值引用

如果使用了完美转发,则可以保持t左值引用的左值引用返回,右值引用的右值引用返回

完美转发forward本质是⼀个函数模板,他主要还是通过引用折叠的方式实现,下面示例中传递给

Function的实参是右值,T被推导为int,没有折叠,forward内部t被强转为右值引用返回;传递给

Function的实参是左值,T被推导为int&,引用折叠为左值引用,forward内部t被强转为左值引用

返回。

复制代码
int main()
{
    // 10是右值,推导出T为int,模板实例化为void Function(int&& t)
    Function(10); // 右值

    int a;
    // a是左值,推导出T为int&,引⽤折叠,模板实例化为void Function(int& t)
    Function(a); // 左值

    // std::move(a)是右值,推导出T为int,模板实例化为void Function(int&& t)
    Function(std::move(a)); // 右值

    const int b = 8;
    // a是左值,推导出T为const int&,引⽤折叠,模板实例化为void Function(const int&t)
    Function(b); // const 左值
    // std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&&t)
    Function(std::move(b)); // const 右值

    return 0;
}

lambda表达式语法

本质是一个匿名函数对象,跟普通函数不同的是它可以定义在函数内部

参数为空可以省略

捕捉为空也不能省略

这里返回值部分可以省略,可以通过返回对象自动推导,写上的话更具有可读性

函数体不可以省略

相比于仿函数的话,lambda表达式需要实现的轻和少(如比大小,仿函数需要实现的就很多,如一个大小需要实现2个仿函数)

lambda不需要取名字,因为本身就是匿名函数对象

捕捉列表

lambda表达式中默认只能用lambda函数体和参数中的变量,如果想用外层作用域中的变量就需要进行捕捉

lambda表达时是可以写在全局的,全局就不需要捕捉,必须为空

局部的静态和全局变量不能捕捉,也不需要捕捉

传值捕捉过来的变量是不可以修改的,就跟被const修饰了一样,是不可以修改的

如果想要修改也是可以,但是这里的++不会影响外面的值,因为传值捕捉始终是拷贝

隐式捕捉
隐式值捕捉

用了哪些就捕捉哪些变量

隐式引用捕捉

用了哪些变量就捕捉哪些变量

混合捕捉

原理

范围for的底层是迭代器,lambda底层是仿函数对象

捕捉到的变量变成仿函数的成员变量

相关推荐
蓝悦无人机14 分钟前
《Planning algorithms》读书笔记——第1章 引言
算法·读书笔记·规划算法·lavalle
Sagittarius_A*33 分钟前
分组密码基础(二):Feistel 结构与 DES 的设计思想
算法·信息安全·密码学·des·数论
废弃的小码农37 分钟前
功能测试--Day07--Python编程基础
开发语言·python
青山木44 分钟前
Hot 100 --- 搜索插入位置
java·数据结构·算法·leetcode
Jul1en_1 小时前
【Claude Code Compact】源码级别的学习上下文压缩
java·前端·学习·github·ai编程
再卷也是菜1 小时前
C++17(下)
c++
fengci.1 小时前
Microweber CMS 未授权路径穿越漏洞(CVE-2026-65694)
android·开发语言·前端·学习·php
XWalnut1 小时前
SpringBoot快速入门
java·spring boot·后端
alexwang2111 小时前
HDU 4348 详细题解
c++·算法·题解·hdu·主席树·可持久化数据结构·可持久化线段树
前端 贾公子1 小时前
第06章:结构化输出 (上)
java·服务器·前端