C++11 lambda表达式

C++11 Lambda表达式 Lambda表达式 C++11的一大特性就是引入了Lambda表达式,并在后续的C++14进行了加强。利用Lambda表达式,可以方便定义和创建匿名函数,一个Lambda表达式表示一个可调用单元,我们可以将其理解为一个未命名的内联函数。 Lambda语法定义 [capture list] (paramters list) mutable exception-> return type{fun... 阅读详情

缘起

最近在读boost.asio的实例代码,其中有使用c++11标准的lambda表达式。都有些看不懂代码的意思。异步调用注册回调函数时,直接使用lambda表达式来制作。在C语言的libEvent通讯库,当一个数据包达到,一个连接建立这样的回调,都是通过函数指针来制作。ACE框架是通过接口类,继承对象之后编写回调函数来做。而在之前boost.asio版本的用法中,基本上都是使用的boost.bind,boost.function库模拟了libevent的函数指针方式。有了匿名函数之后可以更加节约代码,直接在调用的时候,将回调函数写完。这些写法在java、js、c#语言里面很早就有这样的支持。下面是js中通过http模块请求数据的实例:

var http = require('http'), 
  urls = ['www.baidu.com','www.10jqka.com.cn','www.duokan.com']; 
function fetchPage(url){ 
  var start = new Date(); 
  http.get({host:url},function(res){ 
    console.log("Got response from:" + url); 
    console.log("Request took:",new Date() - start, "ms"); 
  }); 
} 
for(var i=0; i<urls.length; i++){ 
  fetchPage(urls[i]); 
} 

匿名函数好处

1.lambda表达式是C++里面的闭包,他也有访问自己域上面的变量的能力。闭包可以理解成“函数绑定了一堆变量”;而相对类比的是类:“类是成员变量绑定了一堆函数”。
2.写起来将会更加灵活小巧,比如说,lambda表达式作为一个函数指针,能被传递给框架代码做一些特殊处理,而且在处理的过程中,我们可以很方便的使用到调用时候的上下文变量,真是左右逢源。(如果使用libEvent写类似代码,可能在设计的开始就要确定好自定义的struct。在注册事件时将数据填充好并且传递给libEvent,当libEvent有事件到达的时候,他将会把这个struct指针传回来。)

代码差异

下面我们来通过两段代码来对比一下c++11标准、c++标准boost.bind方式的代码,在编写boost.asio的accept回调写法的差异:
c++ 11 标准:

void do_accept()
    {
        acceptor_.async_accept(socket_,
            [this](boost::system::error_code ec)
        {
            if (!ec)
            {
                std::make_shared<session>(std::move(socket_))->start();
            }

            do_accept();
        });
    }

c++ 标准:

  void start_accept()
  {
    session* new_session = new session(io_service_);
    acceptor_.async_accept(new_session->socket(),
        boost::bind(&server::handle_accept, this, new_session,
          boost::asio::placeholders::error));
  }
  void handle_accept(session* new_session,
      const boost::system::error_code& error)
  {
    if (!error)
    {
      new_session->start();
    }
    else
    {
      delete new_session;
    }

    start_accept();
  }

两段代码达到了相同的效果。

cppreference_Lambda_表达式

lambda学习笔记:

构造一个闭包:一个无名字函数对象能访问范围中的变量。注意这个lambda表达式是一个闭包。它能访问到自己函数域外部的变量。但是需要通过[capture-list]里面定义lambda表达式的访问方式。

语法

1.[ capture-list ] ( params ) mutable(optional) constexpr(optional)(c++17) exception attribute -> ret { body }
2.[ capture-list ] ( params ) -> ret { body }
3.[ capture-list ] ( params ) { body }
4.[ capture-list ] { body }

1.第一个是全定义模式;
2.申明一个常量lambda:被captured的对象是复制的不能被修改;
3.简略返回值模式:闭包返回值类型依据下面两条规则:
3.1.如果这个body没有任何内容,只有依据return (表达式);时,返回类型就依据返回的类型;(until C++14)
否则将返回void
3.2.返回类型将来自于 return statements随返回类型申明的推导函数。
4.省略掉参数表模式;

解释

mutable

允许body去修改通过值捕获参数内容。

#include <iostream>

int main()
{
    int a = 1, b = 1, c = 1;

    auto m1 = [a, &b, &c]() mutable {
        auto m2 = [a, b, &c]() mutable {
            std::cout << a << b << c << '\n';
            a = 4; b = 4; c = 4;
        };
        a = 3; b = 3; c = 3;
        m2();
    };

    a = 2; b = 2; c = 2;

    m1();                             // calls m2() and prints 123
    std::cout << a << b << c << '\n'; // prints 234
}

如果将mutable去掉

    auto m1 = [a, &b, &c]()  {
        auto m2 = [a, b, &c]()  {
            std::cout << a << b << c << '\n';
            a = 4; b = 4; c = 4;
        };
        a = 3; b = 3; c = 3;
        m2();
    };

将会直接出现这些报错:

1>f:\learn\c++\test_boost\main.cpp(94): error C3491: “a”: 无法在非可变 lambda 中修改通过复制捕获
1>f:\learn\c++\test_boost\main.cpp(94): error C3491: “b”: 无法在非可变 lambda 中修改通过复制捕获
1>f:\learn\c++\test_boost\main.cpp(96): error C3491: “a”: 无法在非可变 lambda 中修改通过复制捕获

在capture-list理解完之后将会更加加深映像。其实定义了mutable之后,将会默认直接把外部的变量都做一个copy的副本来做修改。

exception

抛出异常选项

attributes

lambda属性

capture-list

0~n由,分割符分割的抓取列表,capture-list的开头是使用一个capture-default。下面列举了capture-default的一些实例:

  • [a,&b] 定义a变量传值方式使用,b变量是引用方式使用;
  • [this] 将this指针传值方式加以使用
  • [&,x] x 显示地以传值方式加以使用。其余变量以引用方式加以使用。
  • [=,&z] z 显示地以引用方式加以使用。其余变量以传值方式加以使用。
  • [] 不抓取

读到这里我capture其实是在定义闭包访问scope中变量的方式。不像Lua闭包一样的,在闭包里面如果要访问scope中的变量的时候,需要在这个里面定义访问的规则。

看完这个部分之后大概能看懂了这个代码了:

    void do_read()
    {
        auto self(shared_from_this());
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
            [this, self](boost::system::error_code ec, std::size_t length)
        {
            if (!ec)
            {
                do_write(length);
            }
        });
    }

[this,self]这个的意思是将this和self这个share_ptr指针,以传值方式传递给闭包来使用。

params

就是匿名函数的参数表。

ret

定义lambda表达式的返回值

body

函数实现。

总结:

使用lambda表达式来优化程序还是很有必要。特别是在异步处理的时候,closure在写异步调用能更加符合人的思维方式。

用Verilog搭出RISC-V架构单周期CPU 这是笔者学校暑期学期的必修课,难度并不高(仅追求及格的话),但相当耗时,对于在硬件设计方面完全不感冒的同学更是一场避不开的折磨,所以笔者想通过自己的成果和被折磨经验来帮助有此方面需求的同学,或是对于CPU设计有浓厚兴趣的人。 阅读详情

相关推荐

Emotion-LLaMA实战指南:从零构建多模态情感识别系统(附Python代码)

本文提供了Emotion-LLaMA多模态情感识别系统的实战指南。通过详细的步骤,指导读者从零搭建开发环境、运行本地Demo、理解模型架构,并完成数据处理与模型训练。该创新模型融合视觉、听觉与文本信息,实现更精准、接近人类理解的情感分析与推理,并附有完整的Python代码实现。

weixin_29094775的博客 415

C++11 Lambda 表达式

Lambda 表达式是重载了函数调用运算符 () 的未命名类的未命名对象。 Lambda 表达式可以被认为是一个匿名的函数对象。 与任何函数类似一个 Lambda 表达式包含一个返回类型、一个参数列表、一个函数体。 Lambda 定义 [captuer_list](parameter_list) -> return_type { function_body } captuer_list 是捕获列表,是一个 Lambda 表达式所在函数中定义的局部变量的列表 return_type 是尾置返回,是一

mwl_learning的博客 436

智能体在车联网中的应用:一份详尽到每日的100天学习路线图

这100天的旅程,是一次对毅力、学习方法和工程实践能力的综合考验。它不仅关乎掌握一系列技术点,更关乎培养解决复杂系统性问题的思维模式——将宏观的交通需求分解为微观的智能体决策,再通过多智能体协同涌现出宏观的智能行为。当你完成这份大纲时,你将拥有的不仅是一个项目作品集,更是一套应对“智能体+车联网”乃至更广泛AI+垂直领域挑战的方法论。未来已来,期待你成为构建智能交通新生态的关键贡献者。

IT深耕十余载,大道之简 1332

使用lambda表示式编写connect时,想要赋值给外部变量方法错误信息:Cannot assign to a variable captured by copy

在 C++ 中,当你使用 lambda 表达式捕获变量时,如果默认情况下会按值捕获(即复制),那么你无法修改捕获的变量。如果你尝试在非可变(non-mutable)lambda 中赋值给被捕获的变量,就会出现错误信息:“Cannot assign to a variable captured by copy in a non-mutable lambda”。

qfZYG的博客 587

风力摆控制系统 PCB 设计 3 要点:STM32+MPU6050+空心杯电机驱动一体化

本文详细解析了风力摆控制系统PCB设计的3大核心要点,重点介绍STM32主控、MPU6050姿态传感器与空心杯电机驱动的一体化方案。通过系统架构设计、PCB布局布线技巧以及噪声抑制方案,帮助参赛者在电子设计竞赛中构建高精度、高稳定性的风力摆控制系统,提升竞赛作品性能。

weixin_30363285的博客 359

Android汽车服务篇(一) CarService

本文主要说明了CarService这一系统服务的启动流程,以及一些关键成员的创建和初始化流程.同时简单介绍了一下客户端是如何获取和使用CarService对象, 如上文介绍的, CarService对象只是获取各个Manager的媒介,它本身并不承担管理传感器.空调等具体的任务.如果要获取车辆的相关信息,如车速, 车内空调温度,诊断信息, 或对车辆进行相关的控制,如升高和降低空调温度,控制座椅和车窗, 调节音量等,就要通过具体的Manager中的API和对应的服务来实现了.

u012514113的专栏 8145

C++11之lambda表达式

C++中lambda表达式的介绍与使用

异样旧日的博客 515

C语言——预处理指令

return 0;这里是可以编译通过的,运行结果也是对的:;;return 0;这里编译器会报错:这里是有语法错误的。在C语言中,#include是一个预处理指令,用于将一个源文件的内容插入到另一个源文件中。这通常用于包含标准库或自定义库的头文件,以便在程序中使用这些库中定义的函数、类型和宏。#include或:用于包含标准库头文件。查找策略是,编译器会在标准库头文件目录中查找这些文件。:用于包含用户自定义的头文件。

Stewie Lee的博客 3188

【C++】c++11新特性(二)--Lambda函数及function(包装器)

可选的。

HZ_ENG的博客 2098

软考「系统规划与管理师(第2版)」抱佛脚|案例分析预测

规划类(系统/数据/云)+ 服务过程找错改进 + 风险应急终止三大块各备一套成熟模板,术语统一按第2版新教材口径,案例分析 45 分线的希望就大很多。

软件行业技术文化交流。 71

六、Tool 工具系统:让大模型拥有“手脚“

我问你一个问题:大模型能不能告诉你"北京今天天气怎么样"?能——它能用非常流畅的中文回答你不能——它不知道这个答案因为它没有联网能力,也没有实时数据。它可能会自信地编一个"今天晴,25 度"给你——这就是幻觉。问题出在哪?大模型是一个"推理引擎",不是一个"执行引擎"。它知道天气 API 怎么调用,但不能真的发出 HTTP 请求。它知道 Python 代码怎么写,但不能真的运行代码。它知道数学公式,但做不了精确的大数计算。Tool 工具系统解决的,就是这个"最后一公里"问题。

牛肉胡辣汤 157

C++(30)——lambda表达式原理及应用

lambda lambda这个词起源于数学上的λ,在C++中利用lambda表达式,可以方便的定义和创建匿名函数。lambda可以看做函数对象的升级版。改进了函数对象以下的缺点: 使用在泛型算法中的参数传递的过程中 比较性质/自定义操作 优先级队列 智能指针 lambda表达式语法 [捕获外部变量](形参列表)->返回值{操作代码}; 如果lambda不需要返回值,那么返回值可以省略。也就是这样: [捕获外部变量](形参列表){操作代码}; 捕获外部变量的方式: []:表示不捕获任何外部变量

qq_44824574的博客 1427

基于YOLOv10深度学习的花生种子霉变检测系统

YOLO(You Only Look Once)是当前最先进的目标检测算法之一,具有快速、精准的特性。YOLOv10是YOLO系列的最新版本,相较于之前的版本,YOLOv10在特征提取、模型精度和速度上都有了显著的提升。YOLOv10采用了更深的卷积神经网络、更多的跨层特征融合方法,使得其在不同尺寸物体的检测和复杂场景的处理上都表现出了优异的性能。YOLOv10特别适合应用在需要快速处理并检测大量图像的任务中,如花生种子霉变检测等,能够实现精准、高效的检测。

2201_76125393的博客 648

C++11:lambda表达式

lambda表达式是C++11的一个非常重要的一个语法,可以帮助我们简介代码,如果说右值引用是减轻了编译器的负担,那么lambda表达式就是减轻了程序员写代码的负担。

weixin_51142926的博客 2481

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C++11-lambda表达式

从C++98以来,C++11无疑是一个相当成功的版本更新。它引入了许多重要的语言特性和标准库增强,为C++编程带来了重大的改进和便利。C++11的发布标志着C++语言的现代化和进步,为程序员提供了更多工具和选项来编写高效、可维护和现代的代码。在C++11中。

2401_83603768的博客 1428

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【C++11】lambda表达式

C++lambda表达式

A.的博客 1487

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++ 11 Lambda表达式

原文地址:https://www.cnblogs.com/DswCnblog/p/5629165.html C++11的一大亮点就是引入了Lambda表达式。利用Lambda表达式,可以方便的定义和创建匿名函数。对于C++这门语言来说来说,“Lambda表达式”或“匿名函数”这些概念听起来好像很深奥,但很多高级语言在很早以前就已经提供了Lambda表达式的功能,如C#,Python等。今天,我们就...

键盘上狂欢 5223

C++11——lambda表达式

目录 前言 一.lambda表达式用法 二.lambda表达式语法 三.lambda表达式的原理 前言 在显示生活中,我们在用手机购物时。总是可以在页面上看到下面这样的选项。 我们知道底层这是通过排序来完成的,但是当我们实现时,要写多个排序算法,写多个仿函数来实现不同变量的比较。 比如下面代码: struct CompareNameSmall; struct CompareNameBig; struct ComparePriceSmall; stru...

weixin_57023347的博客 8585

【C++】C++11 lambda表达式

lambda表达式的引入是为了简化代码,提高代码的可读性,在某种角度上来看,lambda表达式实际上是一个匿名函数。

℉f的博客 1637

【C++】C++11——lambda表达式

C++11——Lambda表达式

weixin_60478154的博客 4544

C++11之深度理解lambda表达式

在现代C++中,Lambda表达式提供了一种简洁而强大的方式来定义匿名函数,使代码更具可读性和灵活性。自C++11引入Lambda以来,它已经成为STL算法、并发编程和回调机制中的重要工具。随着C++14、C++17和C++20的不断演进,Lambda的功能也在不断增强,进一步提升了C++语言的表达能力。本文将从Lambda的语法入手,分析其捕捉列表的工作原理,探讨Lambda在实际开发中的应用,并深入剖析Lambda背后的实现原理,帮助大家全面掌握这一强大特性。

2302_79376097的博客 1993

【 C++11 】lambda表达式

目录 1、lambda表达式的引入 2、lambda表达式 lambda表达式的语法 lambda表达式捕捉列表说明 使用lambda表达式排序自定义类型 lambda表达式的底层原理

bit_zyx的博客 3411
上一篇: 逻辑题
下一篇: C++ 11 正则表达式
erlang_hell
博客等级 码龄14年 57粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值