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

如何将带参数on_completion函数的std::barrier传入线程函数

解决C++ std::barrier完成函数访问Data对象的问题

核心思路

std::barrier的完成函数本身不支持接收参数,要让它访问外部Data对象,正确的做法是通过lambda捕获(或其他带状态的可调用对象)来获取Data的引用/指针,而非试图修改完成函数的签名。

修正后的完整代码示例

#include <barrier>
#include <thread>
#include <iostream>

struct Data {
    int value = 0;
};

void thread_function(Data& data, std::barrier<>& bar) {
    // 线程前置工作:修改Data临时值
    data.value += 1;
    // 等待所有线程到达屏障
    bar.arrive_and_wait();
    // 屏障完成后的后续工作
    std::cout << "线程完成屏障同步,当前data值:" << data.value << "\n";
}

int main() {
    const int thread_count = 3;
    Data data;

    // 定义完成函数:通过引用捕获data,在屏障触发时修改对象
    auto completion_func = [&data]() noexcept {
        data.value *= 2; // 示例操作:将data值翻倍
        std::cout << "所有线程到达屏障,已更新data值为:" << data.value << "\n";
    };

    // 初始化barrier:C++20起可自动推导完成函数类型
    std::barrier barrier(thread_count, completion_func);

    // 创建线程:用std::ref传递引用,避免拷贝
    std::thread t1(thread_function, std::ref(data), std::ref(barrier));
    std::thread t2(thread_function, std::ref(data), std::ref(barrier));
    std::thread t3(thread_function, std::ref(data), std::ref(barrier));

    // 等待所有线程执行完毕
    t1.join();
    t2.join();
    t3.join();

    return 0;
}

关键细节说明

  • 捕获外部变量:完成函数lambda通过[&data]引用捕获Data对象,在屏障触发时直接访问并修改它,无需额外传参。
  • barrier类型匹配:线程函数中的barrier参数用std::barrier<>&(自动推导类型的引用),确保和main中定义的barrier类型一致;若需显式指定模板参数,可写为std::barrier<decltype(completion_func)>。
  • 引用传递线程参数:创建线程时必须用std::ref传递data和barrier,否则线程会拷贝对象,导致操作的是副本而非原对象。
  • 生命周期保证:确保Data对象的生命周期覆盖所有线程和barrier的存在周期(示例中main函数的data直到所有线程join后才销毁,符合要求)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:02:43