You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用std::thread时,为何允许传递捕获引用的lambda表达式?

问题

我对cppreference上关于std::thread的说明存在疑问:线程函数的参数会按值移动或复制,若需传递引用参数,必须用std::ref或std::cref包装。这是因为无法保证参数在线程执行期间始终存活,线程应拥有参数所有权。

但如下代码中,直接将mainThreadVariable作为引用参数传给tellValue函数,Clang编译器不接受,这符合预期;而使用捕获引用的lambda表达式作为线程函数时,编译器却接受,且能正确修改mainThreadVariable的值,程序输出正常。为何后者是被允许的?

代码示例1(编译失败)

#include <iostream>
#include <thread>

void tellValue(int& value)
{
    std::cout << "The value is: " << value << std::endl;
}

int main()
{
    int mainThreadVariable{0};

    std::thread thr0{tellValue, mainThreadVariable};

    thr0.join();

    return 0;
}

代码示例2(编译通过且运行正常)

#include <iostream>
#include <thread>

int main()
{
    int mainThreadVariable{0};

    std::thread thr0{[&]()
                     {
                         std::cout << "The value is: " << mainThreadVariable
                                   << std::endl;
                         ++mainThreadVariable;
                     }};

    thr0.join();

    std::cout << "The value is: " << mainThreadVariable << std::endl;

    return 0;
}

程序输出

./PassingArgumentsToAThread 
The value is: 0
The value is: 1
解答

这两种情况的核心区别在于参数传递机制和编译器的检查逻辑:

  1. 代码示例1的报错原因:
    std::thread的构造函数会把传入的参数按值复制/移动到线程内部存储,再尝试将这些副本传递给目标函数tellValue。但tellValue需要的是int&类型的左值引用,线程存储里的副本是右值,无法绑定到非const左值引用上——这就是编译器报错的直接原因。用std::ref包装的本质是把变量引用封装成可复制的对象,线程拿到后解引用出原始引用传递给函数,才能匹配类型要求。

  2. 代码示例2合法的原因:
    lambda捕获引用是让lambda内部代码直接绑定到原始变量mainThreadVariable的引用上。此时std::thread构造函数接收的是lambda对象本身(按值复制这个lambda),而lambda对象里保存的是对原始变量的引用——这和直接传递参数给线程函数的逻辑完全不同:线程没有复制mainThreadVariable,而是lambda带着引用“绑定”了原始变量。

编译器允许这种写法,是因为它只负责检查语法和类型合法性,不会替你判断引用的生命周期是否安全。这个例子里调用了thr0.join(),主线程会等待子线程执行完毕再继续,所以mainThreadVariable在子线程运行期间肯定存活,程序能正常运行。但如果改成thr0.detach(),子线程可能在主线程退出后仍运行,此时引用会变成悬垂引用,行为未定义——编译器不会阻止这种错误,生命周期安全需要开发者自己保证。

简单总结:std::thread处理普通参数时强制复制/移动,类型不匹配就报错;lambda捕获引用是开发者主动选择的绑定,编译器只确保语法正确,风险由开发者承担。

内容的提问来源于stack exchange,提问作者Emiliano Toledo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 11:52:39