考虑如下代码:
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
using namespace std;
int get_count()
{
static int count = 0;
return ++count;
}
class task
{
public:
task(int data) : data_(data) {}
auto lazy_launch()
{
return [*this, count = get_count()]() mutable { // 这里使用*this按值捕获,如果直接捕获this,会有问题
ostringstream oss;
oss << "Done work " << data_ << " (No. " << count
<< ") in thread " << this_thread::get_id() << '\n';
msg_ = oss.str();
calculate();
};
}
void calculate()
{
this_thread::sleep_for(100ms);
cout << msg_;
}
private:
int data_;
string msg_;
};
int main()
{
task t(37);
thread t1{t.lazy_launch()};
thread t2{t.lazy_launch()};
t1.join();
t2.join();
return 0;
}
运行结果:
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:22
Done work 37 (No. 1) in thread 281473391817152
Done work 37 (No. 2) in thread 281473383424448
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:22
Done work 37 (No. 1) in thread 281473675637184
Done work 37 (No. 2) in thread 281473667244480
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:22
Done work 37 (No. 1) in thread 281473119936960
Done work 37 (No. 2) in thread 281473111544256
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:22
Done work 37 (No. 2) in thread 281473806221760
Done work 37 (No. 1) in thread 281473814614464
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:22
Done work 37 (No. 2) in thread 281473281548736
Done work 37 (No. 1) in thread 281473289941440
fine, ok.
如果把注释处改为按this指针捕获,则运行结果为:
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:23
Done work 37 (No. 2) in thread 281473417372096
Done work 37 (No. 2) in thread 281473417372096
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:23
Done work 37 (No. 1) in thread 281473528775104
Done work 37 (No. 1) in thread 281473528775104
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:23
Done work 37 (No. 2) in thread 281473521451456
Done work 37 (No. 2) in thread 281473521451456
hubingbing@siaphisprm02259 ~/PacketForwardAgent/service/src/main/cpp/build> ./01_lambda_capture 20:23
Done work 37 (No. 1) in thread 281473544192448
Done work 37 (No. 1) in thread 281473544192448
很奇怪有没有?
如果按指针捕获,lambda表达式中对成员msg_的修改是同一处,后跑的线程会覆盖先跑的线程,所以打印出来都是一句。而按*this
捕获,lambda表达式中已经对task做了拷贝,两个线程写的msg_不是同一个,因此可以正常输出。