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

std::shared_future按引用传入函数是否合法?如何选择传参方式?

std::shared_future传参相关问题解答

按值传递的合法性

按值传递std::shared_future是合法行为,因为std::shared_future本身支持拷贝操作,示例代码如下:

#include <future>
#include <vector>
#include <iostream>

int factorial(std::shared_future<int> sf)
{
    int res = 1;
    int num = sf.get();

    for(int i=num; i>1; i--)
    {
        res *= i;
    }

    return res;
}

int main()
{
    std::promise<int> prs;
    std::vector<std::future<int>> vec;


    std::shared_future<int> sf{prs.get_future()};
    for(int i=0; i<10; i++)
    {
        vec.push_back(std::async(std::launch::async, factorial, sf));
    }  
    
    prs.set_value(5);

    for(auto& fut: vec)
    {
        std::cout << fut.get() << std::endl;
    }
}

引用传递的合法性验证

将std::shared_future以引用形式传入函数的示例代码如下:

#include <future>
#include <vector>
#include <iostream>

int factorial(std::shared_future<int>& sf)
{
    int res = 1;
    int num = sf.get();

    for(int i=num; i>1; i--)
    {
        res *= i;
    }

    return res;
}

int main()
{
    std::promise<int> prs;
    std::vector<std::future<int>> vec;


    std::shared_future<int> sf{prs.get_future()};
    for(int i=0; i<10; i++)
    {
        vec.push_back(std::async(std::launch::async, factorial, std::ref(sf)));
    }  

    prs.set_value(5);

    for(auto& fut: vec)
    {
        std::cout << fut.get() << std::endl;
    }
}

上述代码片段可正常编译,且看起来运行效果正常。


核心结论

  1. 引用传递的合法性前提
    上述引用传递代码能正常运行,需要同时满足两个条件:

    • 被引用的std::shared_future对象生命周期覆盖所有异步任务的执行全程:示例中sf定义在main函数栈上,主线程通过循环调用fut.get()阻塞等待所有任务执行完成后才会退出,sf不会在任务运行期间被销毁。
    • 不存在并发修改:std::shared_future::get()是线程安全的const成员函数,多个线程同时调用不会产生数据竞争。
      但这种写法存在明确的安全隐患:如果被引用的shared_future提前销毁,异步任务访问悬空引用会触发未定义行为。
  2. 传参方式选择规则
    和std::shared_ptr的传参逻辑一致,两种方式没有绝对对错,需要结合场景选择:

    • 跨线程、异步场景优先选择按值传递:每个持有拷贝的执行单元自行管理共享状态的生命周期,从根源上避免悬空引用风险。shared_future的拷贝仅会增加内部共享状态的引用计数,开销极低,是这类场景下最稳妥的选择。
    • 同一作用域内的同步调用可以使用引用传递:如果能100%保证原shared_future对象的生命周期覆盖被调用方的全部使用流程,按引用传递可以省去一次引用计数增减的微小开销,不存在安全问题。
    • 无生命周期保障的场景禁止使用引用传递:这类场景下悬空引用的风险,远大于引用计数操作带来的微小性能收益。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 09:39:20