作者:手机用户2602901497 | 来源:互联网 | 2023-08-23 17:58
关于lambdacapture:Ifthecapture-defaultis&,subsequentsimplecapturesmustnotbeginwith&.
关于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" <}
当main函数执行到打印“main end”时&#xff0c;a对象已经释放&#xff0c;但是它创建的子线程中调用了它的成员函数依然可以正常执行。这是因为成员函数在转变为汇编代码时与普通的函数一样&#xff0c;只不过会将this指针作为它的第一个参数传入&#xff0c;而且a对象的func()方法中没有调用A的其他成员变量&#xff0c;因此不会发生crash。正确的写法应该是在进入lambda的时候判断此时它capture的this指针所指向的对象是否还是有效的&#xff1a;
#define RETURN_FROM_LAMBDA_IF_DEAD(x) \auto sharedThis &#61; x.lock(); \if(!sharedThis) \return;class A: public std::enable_shared_from_this
{
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 &#61; 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" <}
另外&#xff0c;如果确实想要在lambda中调用this指向对象的成员函数且这个成员函数没有调用成员变量&#xff0c;可以把这个成员函数定义成private static&#xff0c;这样就不会有上面说的问题。
参考链接&#xff1a;
https://en.cppreference.com/w/cpp/language/lambda
https://stackoverflow.com/questions/57654701/member-function-captured-by-lambda-asynchronously-dispatch-issue