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

是否可能在复制shared_ptr前,原shared_ptr已超出作用域?

问题:这段代码是否会输出“Shared Ptr out of scope”?

这段代码片段是否有可能输出“Shared Ptr out of scope”?我想验证的是:在复制shared_ptr之前,原shared_ptr是否会先超出作用域。我知道shared_ptr拥有原子引用计数,但如果Test的拷贝构造函数在shared_ptr复制前被调用,同时主线程中的shared_ptr sp超出作用域,会发生什么?我尝试调整foo函数的参数顺序,结果一致,即代码块执行时会打印“Shared Ptr has value 9”。

struct Test
{
    Test() = default;
    Test(const Test& t)
    {
        using namespace std::chrono_literals;
        for (int i = 0; i < 5; ++i)
        {
            std::cerr << "I am sleeping----\n";
            std::this_thread::sleep_for(2000ms);
        }
    }
};

void foo(std::shared_ptr<int> sp, Test t)
{
    if (sp)
        std::cerr << "Shared Ptr has value "<<*sp;
    else
        std::cerr << "Shared Ptr out of scope";
}
int main()
{
    std::thread t;
    {
        Test tst;
        auto sp = std::make_shared<int>(9);
        t = std::move(std::thread(foo,sp, tst));
    }
    if(t.joinable())
    t.join();
}
回答

不会输出“Shared Ptr out of scope”,原因如下:

  • 创建std::thread对象时,所有传入的参数都会在主线程的当前作用域内完成拷贝,之后才会启动新线程执行目标函数。也就是说,不管参数顺序如何,shared_ptr<int>的复制(会原子性增加引用计数)和Test对象的拷贝构造,都是在主线程的代码块里完成的,此时原sp还未超出作用域。
  • 即便Test的拷贝构造函数耗时很长,整个拷贝过程依然在主线程中执行,直到所有参数拷贝完成、std::thread构造结束后,原作用域的sp和tst才会被销毁。此时shared_ptr的引用计数至少为2(原sp和传给线程的拷贝),原sp销毁后引用计数减为1,传给线程的拷贝依然有效,所以foo中的sp必然是有效的,会输出“Shared Ptr has value 9”。
  • 调整参数顺序不会改变结果,因为所有参数的拷贝操作都发生在新线程启动前、主线程的作用域内,不存在“拷贝Test时原sp先销毁”的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:12:10