博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ lambda
阅读量:7200 次
发布时间:2019-06-29

本文共 3620 字,大约阅读时间需要 12 分钟。

最简单的lambda:

int main(){    auto lambda = []{};    lambda();}

让lambda更有用,就要捕捉局部变量。

#include 
int main(){ int x = 1; auto lambda = [x] { printf("x=%d",x); }; lambda();}

[x]是按值方式的捕捉,而且lambda对应的那个可调用的方法,是const。可以脑补这个等价物:

#include 
int main(){ int x=1; class unnamed_functor{ public: unnamed_functor(int arg): x{arg}{} void operator()() const{
// x=2; 错误,const函数内不能修改成员变量 printf("x=%d",x); } int x; }; unnamed_functor lambda{x}; lambda();}

可以使用mutable重新标记lambda函数,这个标记会清除const标记。例如:

#include 
int main(){ int x = 1; auto lambda = [x] mutable{ x=2; printf("in lambda x=%d\n",x); }; lambda(); printf("x=%d\n",x); }

[&y]是按照引用方式捕捉局部变量。例如:

#include 
int main(){ int x=1, y= 2; auto lambda = [x, &y] { y=3; printf("in lambda y=%d\n",y); }; lambda(); printf("y=%d\n",y); }

可见,按照引用方式捕捉的局部变量,不用标记mutable也能更改y值。脑补如下伪代码:

#include 
int main(){ int x=1,y=2 ; class unnamed_functor{ public: unnamed_functor(int x_, int& y_): x{x_},y(y_){} void operator()() const{ // x=2; 错误,const函数内不能修改成员变量 y=3; printf("in lambda y=%d\n",y); } int x; int& y; }; unnamed_functor lambda(x,y); lambda(); printf("y=%d\n",y); }

这里有个惊人的知识盲点,const成员函数能修改引用数据成员。仔细分析一下,const成员函数,关键意图是不更改对象的状态。对于int& y数据成员,就是不能更改此引用指向的对象。

当检查y=3时,并没有改变y所指向的对象(引用的本质是指针或者对象地址),因此与const不矛盾。这就解释了lambda不用加mutable就能搞定引用捕捉的局部变量的修改问题。

lambda作为一个Callable,可以接受任意调用参数:

int main(){    int x=1;    auto lambda = [x](int arg){ return x+arg; }    std::cout << lambda(2); // show 3}

C++14开始,lambda能有自己的内部状态变量了。从前只有两个状态来源:[]捕捉的局部变量( automatic storage duaration 不能是全局变量)()捕捉的调用参数。

例如:

#include 
auto generator = [x = 0] () mutable { return x++;};int main(){ auto a = generator(); // == 0 auto b = generator(); // == 1 auto c = generator(); // == 2}

脑补一下这个东西的等价物:

#include 
class generator{public: generator():x(0){} int operator()(){ return x++; } int x;};int main(){ auto a = generator(); // == 0 auto b = generator(); // == 1 auto c = generator(); // == 2}

lambda捕捉能力进一步增强,可以捕捉任意的表达式。考虑如下问题:

#include 
#include
int main(){ auto p = std::make_unique
(1); //auto q = p; error:不能copy //auto k = std::move(p); ok: 能move copy auto lambda = [p] { //... };}

显然,传值方式失败了,因为unique_ptr不支持copy。为此,使用C++14的新语法:

#include 
#include
int main(){ auto p = std::make_unique
(1); //auto q = p; error:不能copy //auto k = std::move(p); ok: 能move copy auto lambda = [k=std::move(p)] { //... };}

lambda捕捉this指针的语法:

#include 
#include
struct MyObj { int value{ 123 }; MyObj() = default; MyObj(const MyObj& other){ value = other.value; printf("MyObj(const MyObj& other) \n"); } auto getValueCopy() { return [*this] { return value; }; } auto getValueRef() { return [this] { value=111; return value; }; }};int main(){ MyObj mo; auto valueCopy = mo.getValueCopy(); auto valueRef = mo.getValueRef(); mo.value = 321; valueCopy(); // 123 valueRef(); // 321 printf("%d\n", mo.value); }

参考:https://github.com/AnthonyCalandra/modern-cpp-features#lambda-capture-this-by-value

转载于:https://www.cnblogs.com/thomas76/p/8721903.html

你可能感兴趣的文章
eclipse 中 Android sdk 无法更新的问题
查看>>
PrestaShop 网站后台配置(八)
查看>>
Android--CountDownTimer倒计时工具类
查看>>
linux关于bashrc与profile的区别(转)
查看>>
操作系统知识汇总
查看>>
final发布评论
查看>>
读取Excel二进制写入DB,并从DB中读取生成Excel文件
查看>>
了解.NET框架
查看>>
用java语言写一个简易版本的登录页面,包含用户注册、用户登录、用户注销、修改密码等功能...
查看>>
es6+最佳入门实践(4)
查看>>
R 语言绘制功能富集泡泡图
查看>>
Django默认ORM(一):基本配置
查看>>
详解-vue项目中的文件和目录
查看>>
Android <supports-sceeens>的用法,适应屏幕大小
查看>>
Java
查看>>
【Silverlight】以MVVM友好的方式使用DataGrid的SelectedItems属性
查看>>
Netty源码分析之NioEventLoop(转)
查看>>
linux添加用户所在群组
查看>>
Linux-进程描述(2)之进程标识符进程位置与环境变量
查看>>
MyBatis.Net 配置
查看>>