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

多个对象共用同一shared_ptr的正确方式?解决运行时错误的方案

问题解答

最佳处理方式

直接传递shared_ptr的拷贝(不使用std::move)即可,这也是shared_ptr设计的核心用法——通过拷贝操作安全增加引用计数,让A和B共享同一个C对象的所有权。

修改后的main函数代码:

int main()
{
    std::shared_ptr<C> c = std::make_shared<C>();
    A a(c); // 拷贝shared_ptr,引用计数变为2
    B b(c); // 再次拷贝,引用计数变为3
    return 0;
}

另外,A和B的构造函数可以保持现有写法(传值后用std::move转移到成员变量,能避免额外拷贝,属于合理优化),也可以改成接收const引用再拷贝,效果一致:

// A的构造函数可选写法(B同理)
A(const std::shared_ptr<C>& c) : c_(c) {}

可选方案

除了上述最佳方案,还有几种场景化的处理方式:

  • 提前拷贝后移动:如果一定要用std::move,可以先拷贝出独立的shared_ptr再转移给每个对象,避免原指针被掏空:

    int main()
    {
        std::shared_ptr<C> c = std::make_shared<C>();
        std::shared_ptr<C> c_for_a = c;
        A a(std::move(c_for_a));
        std::shared_ptr<C> c_for_b = c;
        B b(std::move(c_for_b));
        return 0;
    }
    

    这种写法冗余,仅适合某些特殊的所有权转移逻辑场景,日常不推荐。

  • 使用weak_ptr(无需所有权时):如果A或B不需要持有C的所有权,只是需要在C存活时访问它,可以改用std::weak_ptr,避免不必要的引用计数持有:

    class A {
    public:
        A(std::weak_ptr<C> c) : c_(std::move(c)) {}
        void access_c() {
            if (auto locked = c_.lock()) {
                // 安全访问C对象,locked是临时的shared_ptr
            }
        }
    private:
        std::weak_ptr<C> c_;
    };
    
    // main函数中
    std::shared_ptr<C> c = std::make_shared<C>();
    A a(c); // shared_ptr可隐式转换为weak_ptr
    B b(c);
    
  • 传递原始指针(不推荐):如果能严格保证C的生命周期长于A和B,可以传递原始指针,但这种方式完全手动管理生命周期,极易出现悬空指针问题,仅适合极端可控场景。

是否必须为A和B各创建一个C的shared_ptr?

不需要。shared_ptr的核心价值就是让多个智能指针共享同一个对象的所有权,通过引用计数自动管理对象生命周期。只要拷贝shared_ptr,A和B的成员c_就会指向同一个C对象,直到所有shared_ptr都被销毁,C才会被自动释放。

只有当你需要A和B各自拥有独立的C实例时,才需要为它们分别创建shared_ptr(比如调用两次std::make_shared<C>()),但这显然不是当前代码的需求——当前问题是误用std::move导致指针被转移为空,而非需要独立的C对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:52:40