C++17中lambda表达式新增加支持的features

      C++17中对lambda表达式新增加了2种features:lambda capture of *this和constexpr lambda

      1.lambda capture of *this:

      *this:拷贝当前对象,创建副本:捕获*this意味着该lambda生成的闭包将存储当前对象的一份拷贝 。
      this:通过引用捕获
      当你需要捕获一个对象的成员变量时,不能直接去捕获成员变量。需要先去捕获对象的this指针或引用。

*this: simple by-copy capture of the current object[=, *this] {};   // since C++17: OK: captures the enclosing by copy
this: simple by-reference capture of the current object[&, this] {};    // C++11: OK, equivalent to [&][&, this, i] {}; // C++11: OK, equivalent to [&, i]

      测试代码如下:

namespace {class S {
public:void f(){int i{ 0 };auto l1 = [=] { use(i, x); }; // captures a copy of i and a copy of the this pointeri = 1; x = 1; l1();           // calls use(0, 1), as if i by copy and x by referenceauto l2 = [i, this] { use(i, x); }; // same as above, made expliciti = 2; x = 2; l2();					// calls use(1, 2), as if i by copy and x by referenceauto l3 = [&] { use(i, x); }; // captures i by reference and a copy of the this pointeri = 3; x = 2; l3();           // calls use(3, 2), as if i and x are both by referenceauto l4 = [i, *this] { use(i, x); }; // makes a copy of *this, including a copy of xi = 4; x = 4; l4();					 // calls use(3, 2), as if i and x are both by copy}private:int x{ 0 };void use(int i, int x) const { std::cout << "i = " << i << ", x = " << x << "\n"; }
};struct MyObj {int value{ 123 };auto getValueCopy() {return [*this] { return value; }; // C++17}auto getValueRef() {return [this] { return value; }; // C++11}
};class Data {
private:std::string name;public:Data(const std::string& s) : name(s) { }auto startThreadWithCopyOfThis() const {// 开启并返回新线程,新线程将在3秒后使用this:std::thread t([*this] {using namespace std::literals;std::this_thread::sleep_for(3s);std::cout << "name: " << name << "\n";});return t;}
};} // namespaceint test_lambda_17_this()
{//reference: https://en.cppreference.com/w/cpp/language/lambdaS s;s.f();// reference: https://github.com/AnthonyCalandra/modern-cpp-features#lambda-capture-this-by-valueMyObj mo;auto valueCopy = mo.getValueCopy();auto valueRef = mo.getValueRef();std::cout << "valueCopy: " << valueCopy() << ", valueRef: " << valueRef() << "\n"; // valueCopy: 123, valueRef: 123mo.value = 321;valueCopy();valueRef();std::cout << "valueCopy: " << valueCopy() << ", valueRef: " << valueRef() << "\n"; // valueCopy: 123, valueRef: 321std::thread t;{Data d{ "c1" };t = d.startThreadWithCopyOfThis();}   // d不再有效t.join();return 0;
}

      执行结果如下图所示:

      2.constexpr lambda:

      在C++17中lambda表达式可以声明为constexpr。constexpr关键字用于在编译时执行计算。
      自从C++17起,lambda表达式会尽可能的隐式声明constexpr。也就是说,任何只使用有效的编译期上下文(例如,只有字面量,没有静态变量,没有虚函数,没有try/catch,没有new/delete的上下文)的lambda都可以被用于编译期。
      使用编译期上下文中不允许的特性将会使lambda失去成为constexpr的能力,不过你仍然可以在运行时上下文中使用lambda.
      为了确定一个lambda是否能用于编译期,你可以将它声明为constexpr.
      当我们需要一个lambda表达式为constexpr时,我们最好显式的对lambda的表达式进行声明,当编译期不通过时,编译期会告诉我们哪里做错了。

      注意:
      (1).如果lambda表达式声明为constexpr,则需要遵循某些规则:如表达式的主体不应包含非constexpr的代码;
      (2).如果operator()满足constexpr函数的要求,或generic lambda特化为constexpr,则它始终是constexpr;
      (3).如果lambda说明符中使用了关键字constexpr,那么它也是constexpr;
      (4).如果lambda的结果满足constexpr函数的要求,则它是隐式constexpr;
      (5).如果lambda隐式或显式为constexpr,则转换为函数指针会生成constexpr函数;
      (6).如果我们使用编译期lambda初始化一个容器,那么编译器优化时很可能在编译期就计算出容器的初始值.
      (7).自从C++17起,如果lambda被显式或隐式地定义为constexpr,那么生成的函数调用运算符将自动是constexpr.

     测试代码如下:

namespace {constexpr int addOne(int n) { return [n] { return n + 1; }(); } // reference: https://stackoverflow.com/questions/12662688/parentheses-at-the-end-of-a-c11-lambda-expression
constexpr auto addOne2(int n) { return [n] { return n + 1; }; } // 注:上下两条语句的区别
constexpr auto addOne3 = [](int n) { return n + 1; };auto squared = [](auto val) { // 自从C++17起隐式constexprconstexpr int x{ 10 };return val * x;
};// 为了确定一个lambda是否能用于编译期,你可以将它声明为constexpr
auto squared3 = [](auto val) constexpr { return val * val; }; // 自从C++17起
auto squared3i = [](int val) constexpr -> int { return val * val; };// 自从C++17起,如果lambda被显式或隐式地定义为constexpr,那么生成的函数调用运算符将自动是constexpr
auto squared1 = [](auto val) constexpr { return val * val; }; // 编译期lambda调用
constexpr auto squared2 = [](auto val) { return val * val; }; // 编译期初始化squared2
constexpr auto squared4 = [](auto val) constexpr { return val * val; };} // namespaceint test_lambda_17_constexpr()
{// 如果函数调用operator(或generic lambda的特化)为constexpr,则此函数为constexprauto Fwd = [](int(*fp)(int), auto a) { return fp(a); };auto C = [](auto a) { return a; };static_assert(Fwd(C, 3) == 3);// reference: https://github.com/AnthonyCalandra/modern-cpp-features#constexpr-lambdaauto identity = [](int n) constexpr { return n; };static_assert(identity(123) == 123);constexpr auto add = [](int x, int y) {auto L = [=] { return x; };auto R = [=] { return y; };return [=] { return L() + R(); };};static_assert(add(1, 2)() == 3);static_assert(addOne(1) == 2);static_assert(addOne2(1)() == 2);std::cout << "addOne:" << addOne(1) << ", addOne2: " << addOne2(1)() << "\n"; // addOne:2, addOne2: 2static_assert(addOne3(1) == 2);int v = [](int x, int y) { return x + y; }(5, 4);std::cout << "v: " << v << "\n"; // v: 9// 将一个lambda表达式嵌套在另一个lambda表达式中int v2 = [](int x) { return [](int y) { return y * 2; }(x)+3; }(5);std::cout << "v2: " << v2 << "\n"; // v2: 13// reference: https://learn.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170// 当函数对象需要去修改通过副本传入的变量时,表达式必须用mutable修饰int m = 0, n = 0;[&, n](int a) mutable { m = ++n + a; }(4);std::cout << "m:" << m << ", n:" << n << "\n"; // m:5, n:0// 如果lambda的结果满足constexpr函数的要求,则它是隐式constexprauto answer = [](int n) {return 32 + n;};constexpr int response = answer(10);static_assert(response == 42);// reference: https://github.com/MeouSker77/Cpp17/blob/master/markdown/src/ch06.mdstd::array<int, squared(5)> arr;  // 自从C++17起 => std::array<int, 50>// 如果lambda隐式或显式为constexpr,则转换为函数指针会生成constexpr函数auto Increment = [](int n) {return n + 1;};constexpr int(*inc)(int) = Increment;return 0;
}

      执行结果如下图所示:

      lambda表达式的最短方式可以写为:[]{} :其没有参数,没有捕获任何东西,并且也不做实质性的执行。当函数对象需要去修改通过副本传入的变量时,表达式必须用mutable修饰。

      GitHub:https://github.com/fengbingchun/Messy_Test

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/651037.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter接口测试总结

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Jmeter介绍&测试准备 Jmeter介绍&#xff1a;Jmeter是软件…

Linux第36步_创建正点原子的TF-A工作区

创建正点原子的TF-A工作区&#xff0c;目的是想查看正点原子的设备树文件“stm32mp157d-atk.dts”和设备树头文件“stm32mp157d-atk.dtsi”&#xff0c;了解设备树是什么样子&#xff0c;为后期基于“ST公司的源码”创建自己的设备树提供参考&#xff0c;同时也是为了学习移植u…

人体组织展示可视化模型:探索生命奥秘的新窗口

在医学领域&#xff0c;人体组织是研究疾病、生理机制和药物作用的关键。然而&#xff0c;传统的组织学研究方法往往局限于切片观察&#xff0c;难以全面、直观地展示组织结构和功能。随着科技的发展&#xff0c;人体组织展示可视化模型为医学研究带来了革命性的变革。 使用山海…

Mysql第一天

数据库概述 1. 为什么要使用数据库 持久化(persistence)&#xff1a;把数据保存到可掉电式存储设备中以供之后使用。(可掉电:内存 使用高电压和低电压来区别0和1进行数据的一个存储但是一旦断电了电压都没了 0和1也就没有了)大多数情况下&#xff0c;特别是企 业级应用&#…

计算机毕业设计 | SpringBoot 求职招聘管理系统(附源码)

1&#xff0c;绪论 1.1 开发背景 高学历人群是网络求职者的主体&#xff0c;且结构趋向固定。而在疫情肆虐的今日&#xff0c;线上招聘成了越来越多企业和个人选择的方式。在疫情期间线下招聘转为线上招聘&#xff0c;是疫情防控的需要。不能否定的是新的招聘模式的出现一定会…

大创项目推荐 行人重识别(person reid) - 机器视觉 深度学习 opencv python

文章目录 0 前言1 技术背景2 技术介绍3 重识别技术实现3.1 数据集3.2 Person REID3.2.1 算法原理3.2.2 算法流程图 4 实现效果5 部分代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习行人重识别(person reid)系统 该项目…

机器学习 | 利用Pandas进入高级数据分析领域

目录 初识Pandas Pandas数据结构 基本数据操作 DataFrame运算 文件读取与存储 高级数据处理 初识Pandas Pandas是2008年WesMcKinney开发出的库&#xff0c;专门用于数据挖掘的开源python库&#xff0c;以Numpy为基础&#xff0c;借力Numpy模块在计算方面性能高的优势&am…

Android如何通过按钮实现页面跳转方法

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;在Android应用开发中&#xff0c;页面跳转是一项基本且常见的功能。通过按钮实现页面跳转可以为用户提供更好的交互体验&#xff0c;使应用更加灵活和易用。本文将介绍Android Studio中如何通过按钮实现页面跳转的方法&#xf…

JVM简介

一、什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组…

vivado 放置I/O端口

放置I/O端口 I/O规划视图布局提供了几种将I/O端口分配给封装引脚的方法。你可以在“I/O端口”窗口中选择单个I/O端口、I/O端口组或接口&#xff0c;然后分配将它们封装到封装窗口中的封装引脚或设备窗口中的I/O焊盘。在“程序包”窗口中&#xff0c;您可以&#xff1a; •将端…

飞机发动机和飞机压缩机的关系是什么?各自的作用是什么?飞机压缩机类似于汽车涡轮增压器吗?

问题描述&#xff1a;飞机发动机和飞机压缩机的关系是什么&#xff1f;各自的作用是什么&#xff1f;飞机压缩机类似于汽车涡轮增压器吗&#xff1f; 问题解答&#xff1a; 飞机发动机和飞机压缩机是飞机涡轮引擎中的两个主要组成部分&#xff0c;它们共同协作以产生推力&…

基于springboot+vue的明星周边产品销售网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

redis哨兵机制

1)哨兵机制本质上是通过独立的进程来体现的&#xff0c;和之前的redis-server进程是完全不同的进程&#xff0c;redis-sentinel不负责存储数据&#xff0c;只是针对于其他的redis-server进程起到监控的效果&#xff0c;但是通常来说哨兵节点&#xff0c;也会搞一个集合&#xf…

Kotlin快速入门系列2

Kotlin的基本数据类型 Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等。不同于 Java 的是&#xff0c;字符不属于数值类型&#xff0c;是一个独立的数据类型。 Java和kotlin数据类型对照如下&#xff1a; Java基本数据类型 Kotlin对象数据类型 数据类…

goland课程管理(6)

项目目录结构如下图所示&#xff1a; core包下面&#xff1a; class.go package coreimport "github.com/gin-gonic/gin"func Class1(ctx *gin.Context) {}course.go package coreimport (. "cookie/database". "cookie/model""fmt"…

【Python】02快速上手爬虫案例二:搞定验证码

文章目录 前言1、不要相信什么验证码的库2、以古诗文网为例&#xff0c;获取验证码1&#xff09;code_result.py2&#xff09;gsw.py 前言 提示&#xff1a;以古诗文网为例&#xff0c;获取验证码&#xff1a; 登录&#xff1a;https://so.gushiwen.cn/user/login.aspx 1、不…

C++笔记之作用域解析符::和命名空间、作用域的关系

C++笔记之作用域解析符::和命名空间、作用域的关系 —— 杭州 2024-01-26 code review 文章目录 C++笔记之作用域解析符::和命名空间、作用域的关系1.`命名空间`和`作用域`两个术语的联系和区别命名空间(Namespace)作用域(Scope)联系与区别2.`作用域解析符::`和`命名空间`…

Stable Diffusion插件Recolor实现黑白照片上色

今天跟大家分享一个使用Recolor插件通过SD实现老旧照片轻松变彩色&#xff0c;Recolor翻译过来的含义就是重上色&#xff0c;该模型可以保持图片的构图&#xff0c;它只会负责上色&#xff0c;图片不会发生任何变化。 一&#xff1a;插件下载地址 https://github.com/pkuliyi…

(2024,预训练和微调扩散,图编码器,图特征与CLIP特征对齐)场景图到图像合成:集成 CLIP 指导与扩散模型中的场景图条件

Scene Graph to Image Synthesis- Integrating CLIP Guidance with Graph Conditioning in Diffusion Models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 3. 方法 3.1 扩…

Hugo使用且部署GitHubPages

hugo的使用 20201121 Hugo是由Go语言实现的静态网站生成器。简单、易用、高效、易扩展、快速部署。 安装Hugo 0.windows安装(releases) 下载地址&#xff1a;https://github.com/spf13/hugo/releases。 配置环境变量 验证测试是否安装成功 hugo help1. 二进制安装&#xf…