当前位置: 首页 > article >正文

C++11详解(下)

目录

STL中一些变化

lambda

lambda表达式语法

捕捉列表

lambda的应用

lambda的原理

包装器

bind


我们接上!

STL中一些变化

  • 下图1圈起来的就是STL中的新容器,但是实际最有⽤的是unordered_map和unordered_set。这 两个我们前⾯已经进⾏了⾮常详细的讲解,其他的⼤家了解⼀下即可。
  • STL中容器的新接⼝也不少,最重要的就是右值引⽤和移动语义相关的push/insert/emplace系列 接⼝和移动构造和移动赋值,还有initializer_list版本的构造等,这些前⾯都讲过了,还有⼀些⽆关 痛痒的如cbegin/cend等需要时查查⽂档即可。

lambda

lambda表达式语法

  • 它的表达式本质是⼀个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。它的表达式语法使⽤层⽽⾔没有类型,所以我们⼀般是⽤auto或者模板参数定义的对象去接lambda对象。
  • [capture - list]:捕捉列表,该列表总是出现在 判断接下来的代码是否为 lambda 函数的开始位置,编译器根据[]来 lambda 函数,捕捉列表能够捕捉上下⽂中的变量供 lambda 函数使 ⽤,捕捉列表可以传值和传引⽤捕捉。捕捉列表为空也不能省略
  • parameters:参数列表,与普通函数的参数列表功能类似,如果不需要参数传递,则可以连 同()⼀起省略
  • function boby :返回值类型,⽤追踪返回类型形式声明函数的返回值类型,没有返回值时此 部分可省略。⼀般返回值类型明确情况下,也可省略,由编译器对返回类型进⾏推导。

例子:

省略:

捕捉列表

  • lambda 表达式中默认只能⽤  lambda 函数体和参数中的变量,如果想⽤外层作⽤域中的变量就需要进⾏捕捉。
  • 第⼀种捕捉⽅式是在捕捉列表中显⽰的传值捕捉和传引⽤捕捉,捕捉的多个变量⽤逗号分割。[x, y,&z]表⽰x和y值捕捉,z引⽤捕捉。
  • 第⼆种捕捉⽅式是在捕捉列表中隐式捕捉,我们在捕捉列表写⼀个=表⽰隐式值捕捉,在捕捉列表 写⼀个&表⽰隐式引⽤捕捉,这样我们 lambda 表达式中⽤了那些变量,编译器就会⾃动捕捉那些 变量。
  • 第三种捕捉⽅式是在捕捉列表中混合使⽤隐式捕捉和显⽰捕捉。[=,&x]表⽰其他变量隐式值捕捉, x引⽤捕捉;[&,x,y]表⽰其他变量引⽤捕捉,x和y值捕捉。当使⽤混合捕捉时,第⼀个元素必须是 &或=,并且&混合捕捉时,后⾯的捕捉变量必须是值捕捉,同理=混合捕捉时,后⾯的捕捉变量必 须是引⽤捕捉。
  • lambda 表达式如果在函数局部域中,他可以捕捉 lambda 位置之前定义的变量,不能捕捉静态 局部变量和全局变量,静态局部变量和全局变量也不需要捕捉。 lambda 表达式中可以直接使用,这也意味着 lambda 表达式如果定义在全局位置,捕捉列表必须为空。

值捕捉:

隐式引用捕捉:

混合捕捉:

注意:

lambda的应用

  • 在学习 lambda 表达式之前,我们的使⽤的可调⽤对象只有函数指针和仿函数对象,函数指针的 类型定义起来⽐较麻烦,仿函数要定义⼀个类,相对会⽐较⿇烦。而使用lambda去定义可调⽤对像,简单又方便!

我们来看看差别:

lambda:

lambda的原理

lambda底层是仿函数对象,也就说我们写了⼀个lambda,编译器会生成一个对应的仿函数的类!

仿函数的类名是编译按⼀定规则⽣成的,保证不同的 lambda ⽣成的类名不同,lambda参数/返 回类型/函数体就是仿函数operator()的参数/返回类型/函数体, lambda 的捕捉列表本质是⽣成 的仿函数类的成员变量,也就是说捕捉列表的变量都是 lambda 类构造函数的实参,当然隐式捕 捉,编译器要看使⽤哪些就传那些对象。

包装器

  • std::function 是⼀个类模板,也是⼀个包装器。 std::function 的实例对象可以包装存储其他的可以调⽤对象,包括函数指针,仿函数,lambda,bind等表达式。
  • 注意包头文件:functional

应用:

也能再包装:

继续看:

有这么一个类:

注意:

1.拿到非静态函数的地址,需要利用&运算符,而静态函数可以直接用函数名!

2.类中的静态成员函数因为只有形参(没有this指针),所以包装器只需要传形参类型即可,但是类中普通的成员函数因为有this指针,所以包装器需要传类的指针(this指针)!

我们来看看:

普通成员函数的包装:

bind

  • bind 是⼀个函数模板,它也是⼀个可调用对象的包装器,可以把他看做⼀个函数适配器,对接收的fn可调⽤对象进⾏处理后返回⼀个可调用对象
  • bind也在functional头文件中!
  • 调⽤bind的⼀般形式: auto newCallable = bind(callable,arg_list); 其中 newCallable本⾝是⼀个可调⽤对象,arg_list是⼀个逗号分隔的参数列表,对应给定的callable的 参数。当我们调⽤newCallable时,newCallable会调⽤callable,并传给它arg_list中的参数。
  • arg_list中的参数可能包含形如_n的名字,其中n是⼀个整数,这些参数是占位符,表⽰ newCallable的参数,它们占据了传递给newCallable的参数的位置。数值n表⽰⽣成的可调⽤对象 中参数的位置:_1为newCallable的第⼀个参数,_2为第⼆个参数,以此类推。_1/_2/_3....这些占 位符放到placeholders的⼀个命名空间中。

注意:因为bind可以包装可调用对象,又返回可调用对象,所以可以包装函数指针,仿函数,lambda,function类型对象,和bind包装对象,但又因为function可以包装可调用对象,所以它能包装bind!

应用:

bind可以包装函数指针:

包装lambda:

包装仿函数:

包装function类型对象:

包装自己:

function能包装bind!

我们看一个例子:

我们继续看:

好了,C++11我们已经基本讲完,我们下期见!


http://www.kler.cn/a/571461.html

相关文章:

  • MongoDB安全管理
  • 3-2安卓中的目录结构以及核心四大组件应用
  • python3.13安装教程【2025】python3.13超详细图文教程(包含安装包)
  • 人工智能之数学基础:n阶行列式
  • 【高并发内存池】申请内存
  • 浅谈DeepSeek使用技巧
  • 【AI文章解读】The Model is the Product
  • UML之参与者(Actor)
  • Linux《基础开发工具(上)》
  • 蓝桥杯训练—召唤数学精灵
  • C++第六节:stack和queue
  • 文件上传复现
  • React Refs:深入理解与最佳实践
  • 在实际工作中,设计测试用例会用到的设计方法有哪些,请具体举例说明
  • Mlivus:索引类型对比
  • C++07(继承)
  • TCP为什么需要三次握手,两次不行吗?
  • SpringCloud系列教程(十二):网关配置动态路由
  • 前端怎么排查幽灵依赖
  • k8s面试题总结(九)