[C++] - lambda capture的成员函数 异步调用
关于lambda capture:
If the capture-default is &
, subsequent simple captures must not begin with &
.
struct S2 { void f(int i); };
void S2::f(int i)
{[&]{}; // OK: by-reference capture default[&, i]{}; // OK: by-reference capture, except i is captured by copy[&, &i] {}; // Error: by-reference capture when by-reference is the default[&, this] {}; // OK, equivalent to [&][&, this, i]{}; // OK, equivalent to [&, i]
}
If the capture-default is =
, subsequent simple captures must begin with &
or be *this
(since C++17) or this
(since C++20).
struct S2 { void f(int i); };
void S2::f(int i)
{[=]{}; // OK: by-copy capture default[=, &i]{}; // OK: by-copy capture, except i is captured by reference[=, *this]{}; // until C++17: Error: invalid syntax// since c++17: OK: captures the enclosing S2 by copy[=, this] {}; // until C++20: Error: this when = is the default// since C++20: OK, same as [=]
}
Any capture may appear only once:
struct S2 { void f(int i); };
void S2::f(int i)
{[i, i] {}; // Error: i repeated[this, *this] {}; // Error: "this" repeated (C++17)
}
如果lambda capture的是成员函数,这个lambda在它所capture的类对象释放后异步调用:
class A:
{
public:int func(){std::ofstream myfile("example.txt");if (myfile.is_open()){myfile << "Write from child thread.\n";myfile.close();}else{std::cout << "Unable to open file";}}void detach(){std::thread t([this]() {std::this_thread::sleep_for(std::chrono::milliseconds(3000));func();});t.detach();}
};int main()
{{A a;a.detach();}std::cout << "main end" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(5000));return 0;
}
当main函数执行到打印“main end”时,a对象已经释放,但是它创建的子线程中调用了它的成员函数依然可以正常执行。这是因为成员函数在转变为汇编代码时与普通的函数一样,只不过会将this指针作为它的第一个参数传入,而且a对象的func()方法中没有调用A的其他成员变量,因此不会发生crash。正确的写法应该是在进入lambda的时候判断此时它capture的this指针所指向的对象是否还是有效的:
#define RETURN_FROM_LAMBDA_IF_DEAD(x) \auto sharedThis = x.lock(); \if(!sharedThis) \return;class A: public std::enable_shared_from_this<A>
{
public:int func(){std::ofstream myfile("example.txt");if (myfile.is_open()){myfile << "Write from child thread.\n";myfile.close();}else{std::cout << "Unable to open file";}}void detach(){std::thread t([weakThis = weak_from_this(), this]() {RETURN_FROM_LAMBDA_IF_DEAD(weakThis);std::this_thread::sleep_for(std::chrono::milliseconds(3000));func();});t.detach();}
};int main()
{{A a;a.detach();}std::cout << "main end" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(5000));return 0;
}
另外,如果确实想要在lambda中调用this指向对象的成员函数且这个成员函数没有调用成员变量,可以把这个成员函数定义成private static,这样就不会有上面说的问题。
参考链接:
https://en.cppreference.com/w/cpp/language/lambda
https://stackoverflow.com/questions/57654701/member-function-captured-by-lambda-asynchronously-dispatch-issue
[C++] - lambda capture的成员函数 异步调用相关推荐
- static成员函数不能调用non-static成员函数
1 一般类静态成员函数不能调用非静态成员函数 2 static成员函数可以调用构造函数吗? 答案是肯定的,由于static成员函数没有this指针,所以一般static成员函数是不能访问non-sta ...
- Cpp 对象模型探索 / 类普通成员函数的调用方式
C++设计时有一个要求,类普通成员函数的调用性能要和全局函数差不多.所以编译器在处理类的普通成员函数的宗旨是将其当作全局函数来处理. 为了达到上述目的,编译器会对类的普通成员函数进行如下操作: 在函数 ...
- 关于常成员函数对非常成员函数的调用问题
常成员函数不能调用非常成员函数: 比如: #include<iostream> using namespace std; class A {const void print(){cout& ...
- Direct3D Draw函数 异步调用原理解析
概述 在D3D10中,一个基本的渲染流程可分为以下步骤: 清理帧缓存: 执行若干次的绘制: 通过Device API创建所需Buffer: 通过Map/Unmap填充数据到Buffer中: 将Buff ...
- dojo——AMD(二、AMD中class内部成员函数相互调用实现)
一.引言 这两天写arcgis javascript代码的时候,自己以为对dojo的amd规范掌握了,可是后来碰到了一个问题,在每个module中成员函数调用另外一个成员函数必须使用this调用(这点 ...
- C++ 成员函数连续调用
使用 c++ 一些表示灵活数据体的对象时,经常会看到形如 a.reshape({1, 2}).add(1) 这样连续的成员函数调用,这是怎么实现的呢?其实很简单,只需要让需要被连续调用的成员函数最后返 ...
- c++成员函数的调用——常成员函数
1.4-5 成员函数的选择调用一一常成员函数 (15 分) 类中的常对象选择调用常成员函数.语法要点: 如果将一个对象说明为常对象,则通过该常对象只能调用它的常成员函数,而不能调用其他成员函数.补充完 ...
- C++类static成员函数的调用
class中的静态成员函数作用再整个类的内部,对应类的所有实例是共享静态成员函数的,在调用静态成员函数的时候跟调用非静态成员函数是有区别的.另外,静态成员函数只能访问对应类内部的静态数据成员,否则会出 ...
- java 成员函数相互调用_java 深入理解内部类以及之间的调用关系
什么是内部类 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ...
最新文章
- 修Bug哪家强?谷歌:Linux,比我都修得好
- Linux SWAP分区占用率高,刷新SWAP分区方法
- python毫秒级时间戳
- python有趣小程序 表白-抖音最火的整蛊表白小程序如何做出来的?教你用python做出...
- 通过checkbox选择以逗号拼接删除字符串
- linkbutton控件中使用CommandName属性和CommandArgument属性
- iOS 搜狗输入法键盘唤不出的解决办法
- 概率论-4.4 特征函数(待补充)
- Golang学习 - sync 包
- java递推_【Java】递归递推的应用
- Delegate示例
- 蓝丝雨dnf刷图脚本制作
- 揭秘360手机助手未经用户同意,自动开启辅助的“黑科技”
- 如何正确的使用国产杀毒软件
- 软件测试之如何测试数据?
- 掌握命令结构,详解monkey命令
- 利用脚手架创建vue项目时报这个错误,哪位大神帮忙解答一下,实在是找到解决办法了。万分感谢
- 解决光驱不能读盘问题
- 【贺图】子兮祝您2015年新春快乐!
- 受壁虎启发,材料公司Felsuma研发一种能黏在任何材质表面的“壁虎皮肤”
热门文章
- python使用logging模块记录日志
- 迈达斯cdn使用说明_快速了解CDN是什么
- MATLAB在运筹学背包问题的应用,运筹学论文之二维背包问题.docx
- kaggle房价预测特征意思_Kaggle之预测房价
- 使用拷贝的方式(adb push) 绕过Android系统和adb install直接安装APK
- 计算机组成原理第二版知识大纲
- sqlserver缓存程序-只能使用一次清除缓存计划
- 虚拟仿真引擎消息机制
- FileTracker:error FTK1011编译错误的原因和解决办法
- 修改Tomcat欢迎界面为自己项目界面