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 pointer
		i = 1; x = 1; l1();           // calls use(0, 1), as if i by copy and x by reference

		auto l2 = [i, this] { use(i, x); }; // same as above, made explicit
		i = 2; x = 2; l2();					// calls use(1, 2), as if i by copy and x by reference

		auto l3 = [&] { use(i, x); }; // captures i by reference and a copy of the this pointer
		i = 3; x = 2; l3();           // calls use(3, 2), as if i and x are both by reference

		auto l4 = [i, *this] { use(i, x); }; // makes a copy of *this, including a copy of x
		i = 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;
	}
};

} // namespace

int test_lambda_17_this()
{
	//reference: https://en.cppreference.com/w/cpp/language/lambda
	S s;
	s.f();


	// reference: https://github.com/AnthonyCalandra/modern-cpp-features#lambda-capture-this-by-value
	MyObj mo;
	auto valueCopy = mo.getValueCopy();
	auto valueRef = mo.getValueRef();
	std::cout << "valueCopy: " << valueCopy() << ", valueRef: " << valueRef() << "\n"; // valueCopy: 123, valueRef: 123

	mo.value = 321;
	valueCopy();
	valueRef();
	std::cout << "valueCopy: " << valueCopy() << ", valueRef: " << valueRef() << "\n"; // valueCopy: 123, valueRef: 321


	std::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起隐式constexpr
	constexpr 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; };

} // namespace

int test_lambda_17_constexpr()
{
	// 如果函数调用operator(或generic lambda的特化)为constexpr,则此函数为constexpr
	auto 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-lambda
	auto 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: 2
	static_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函数的要求,则它是隐式constexpr
	auto 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.md
	std::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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言-指针的基本知识(下)

四、指针的分类 按指针指向的数据的类型来分 1:字符指针 字符型数据的地址 char *p;//定义了一个字符指针变量&#xff0c;只能存放字符型数据的地址编号 char ch; p &ch; 2&#xff1a;短整型指针 short int *p;//定义了一个短整型的指针变量p&#xff0c…

[Raspberry Pi]如何利用ssh將樹莓派切換連接至陌生的wifi基地台?

當已習慣使用VNC遠端控制樹莓派後&#xff0c;原用來設定樹莓派的電腦螢幕和鍵盤也逐漸挪為它用。此次攜帶樹莓派外出&#xff0c;同時又希望使樹莓派連接當地的wifi AP&#xff0c;利用VNC遠端桌面切換新的wifi AP需要重新設定wifi密碼&#xff0c;但卻無法在VNC遠端桌面看到密…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-2 JavaScript 获取HTML元素对象

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>JavaScript 获取 HTML 元素对象</title> </head><body> <input type"text" value"admin" /> <br> <input …

代码随想录算法训练DAY29|回溯5

算法训练DAY29|回溯5 491.递增子序列 力扣题目链接 给定一个整型数组, 你的任务是找到所有该数组的递增子序列&#xff0c;递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 说…

canvas绘制旋转的大风车

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

Android Handler完全解读

一&#xff0c;概述 Handler在Android中比较基础&#xff0c;本文笔者将对此机制做一个完全解读。读者可简单参考上述类图与时序图&#xff0c;便于后续理解。 二&#xff0c;源码解读 1&#xff0c;主线程伊始 众所周知&#xff0c;通过Zygote的fork方式&#xff0c;新创建…

Unity应用在车机上启动有概率黑屏的解决方案

问题描述 最近将游戏适配到车机上&#xff08;Android系统&#xff09;&#xff0c;碰到了一个严重bug&#xff0c;启动的时候有概率会遇到黑屏&#xff0c;表现就是全黑&#xff0c;无法进入Unity的场景。 经过查看LogCat日志&#xff0c;也没有任何报错&#xff0c;也没有任…

DLL劫持之IAT类型(Loadlibrary)

Loadlibrary Loadlibrary的底层是LoadLibraryEx 第三个参数&#xff1a; DONT_RESOLVE_DLL_REFERENCES : 这个标志用于告诉系统将DLL映射到调用进程的地址空间中&#xff0c;但是不调用DllMain并且不加载依赖Dll&#xff08;只映射自己本身&#xff09;。 LOAD_LIBRARY_AS_DA…

LVGL v9学习笔记 | 12 - 弧形控件的使用方法(arc)

一、arc控件 arc控件的API在lvgl/src/widgets/arc/lv_arc.h 中声明,以lv_arc_xxx命名。 arc控件由背景圆弧和前景圆弧组成,前景圆弧的末端有一个旋钮,前景圆弧可以被触摸调节。 1. 创建arc对象 /*** Create an arc object* @param parent pointer to an object, it w…

(N-141)基于springboot,vue网上拍卖平台

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 系统分前后台&#xff0c;项目采用前后端分离 前端技术&#xff1a;vueelementUI 服务端技术&#xff1a;springbootmybatis-plusredi…

利用STM32CubeMX和Keil模拟器,3天入门FreeRTOS(5.2) —— 互斥量

前言 &#xff08;1&#xff09;FreeRTOS是我一天过完的&#xff0c;由此回忆并且记录一下。个人认为&#xff0c;如果只是入门&#xff0c;利用STM32CubeMX是一个非常好的选择。学习完本系列课程之后&#xff0c;再去学习网上的一些其他课程也许会简单很多。 &#xff08;2&am…

[蓝桥杯]真题讲解:岛屿个数(BFS遍历图)

[蓝桥杯]真题讲解&#xff1a;岛屿个数&#xff08;BFS遍历图&#xff09; 一、视频讲解二、暴力代码&#xff08;也是正解代码&#xff09; 一、视频讲解 视频讲解 二、暴力代码&#xff08;也是正解代码&#xff09; //岛屿个数&#xff1a;搜索&#xff08;BFS/DFS&…

深度推荐模型之DeepFM

一、FM 背景&#xff1a;主要解决大规模稀疏数据下的特征组合遇到的问题&#xff1a;1. 二阶特征参数数据呈指数增长 怎么做的&#xff1a;对每个特征引入大小为k的隐向量&#xff0c;两两特征的权重值通过计算对应特征的隐向量内积 而特征之间计算点积的复杂度原本为 实际应…

华为二层交换机与防火墙配置上网示例

二层交换机与防火墙对接上网配置示例 组网图形 图1 二层交换机与防火墙对接上网组网图 二层交换机简介配置注意事项组网需求配置思路操作步骤配置文件相关信息 二层交换机简介 二层交换机指的是仅能够进行二层转发&#xff0c;不能进行三层转发的交换机。也就是说仅支持二层…

HCIA真机实验:三层交换机实现vlan之间的通信(内含配置命令)

基础实验示例&#xff1a; 最上面那个交换机作为三层交换机。 下面的两个交换机的配置与之前单臂路由实现vlan之间的通信的配置相同。在这个基础上开启三层交换机 在三层交换机上的配置&#xff1a; 1、创建vlan&#xff08;底下的交换机有多少个vlan&#xff0c;则三层交换…

Redis数据类型及底层实现

文章目录 1.3.1 5种基本数据类型1.3.1.1 总结篇1.3.1.2 底层源码引入篇1.3.1.2.1 redis是字典数据库KV键值对到底是什么1.3.1.2.2 数据类型视角1.3.1.2.3 数据模型解析&#xff08;重点&#xff09;1.3.1.2.4 redisObjec1.3.1.2.5 SDS 1.3.1.3 String1.3.1.3.1 底层分析1.3.1.3…

Python环境下基于机器学习的NASA涡轮风扇发动机剩余使用寿命RUL预测

本例所用的数据集为C-MAPSS数据集&#xff0c;C-MAPSS数据集是美国NASA发布的涡轮风扇发动机数据集&#xff0c;其中包含不同工作条件和故障模式下涡轮风扇发动机多源性能的退化数据&#xff0c;共有 4 个子数据集&#xff0c;每个子集又可分为训练集、 测试集和RUL标签。其中&…

【Midjourney】内容展示风格关键词

1.几何排列(Geometric) "Geometric" 是一个与几何有关的词汇&#xff0c;通常用于描述与形状、结构或空间几何特征相关的事物。这个词可以涉及数学、艺术、工程、计算机图形学等多个领域。 使用该关键词后&#xff0c;图片中的内容会以平面图形拼接的方式展示&#…

计算机网络——虚拟局域网+交换机基本配置实验

1.实验题目 虚拟局域网交换机基本配置实验 2.实验目的 1.了解交换机的作用 2.熟悉交换机的基本配置方法 3.熟悉Packet Tracer 7.0交换机模拟软件的使用 4.掌握在交换机上划分局域网&#xff0c;并且使用局域网与端口连接&#xff0c;检测信号传输 3.实验任务 1.了解交换…

springboot项目开发,使用thymeleaf前端框架的简单案例

springboot项目开发,使用thymeleaf前端框架的简单案例&#xff01;我们看一下&#xff0c;如何在springboot项目里面简单的构建一个thymeleaf的前端页面。来完成动态数据的渲染效果。 第一步&#xff0c;我们在上一小节&#xff0c;已经提前预下载了对应的组件了。 如图&#x…