考虑如下代码:

#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_不是同一个,因此可以正常输出。