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底层是仿函数对象

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

相关推荐
得物技术21 小时前
得物推荐系统诊断 Agent:从 “调接口” 到 “会思考”|AICon 演讲整理
人工智能·算法·架构
花生智源21 小时前
Java实现Prompt工程的技巧——从模板到工程化,告别字符串拼接
java·人工智能
Lugas21 小时前
为啥说男生找对象尽量在25岁前找到?
算法
北冥you鱼21 小时前
Go语言与默克尔树:区块链数据完整性的基石
开发语言·golang·区块链
MrZhao40021 小时前
从能跑到可用:一个 Agent Harness 还差哪些工程闭环?
算法
折哥的程序人生 · 物流技术专研21 小时前
Java 23 种设计模式:从踩坑到精通 | 番外:策略 vs 模板方法 —— 组合与继承的终极对决
java·策略模式·java面试·comparator·模版方法模式·java设计模式·从踩坑到精通
库克克21 小时前
【C++】类和对象--this指针详解
java·开发语言·c++
SL_staff1 天前
JVS低代码完整源码解析:如何二次开发自己的表单组件?
java·低代码·vuex
ch0sen1pm1 天前
加班之余从零写了个 spdlog 风格的日志库
c++
JackieZhengChina1 天前
image-viewer-js 开源图片查看插件完整教程
开发语言·javascript·开源