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

如何从原始指针创建shared_ptr,实现多Parent共享管理Child生命周期?

问题描述

我有一组通过组合(而非继承)实现层级关系的类:Child和Parent。Child可拥有多个Parent,Parent也可拥有多个Child。我希望由Parent类管理Child类的生命周期。

当前类结构如下:

class Parent
{
public:
std::shared_ptr<Child> my_chld;
};

class Child
{
...some stuff...
public:
void setParent(Parent* parent)
{
parent->my_child=this;
}
};

main()函数代码如下:

Parent* prnt1=new Parent();
Parent* prnt2=new Parent();
Child* chld=new Child();
chld->setParent(prnt1);
chld->setParent(prnt2);
delete prnt1;

我希望chld在所有Parent都销毁后才释放(即由这些Parent共同管理其生命周期),该如何实现?当前版本中my_chld无法感知其他指针管理同一对象,这是问题所在。或者这种方法完全错误?

补充说明:我正在开发类似Qt的GUI库,当前实现动画系统:同一动画(即Child)可用于多个场景(如多个动画组(即Parent)或其他对象)。我希望在main中保留原始指针,如同其他框架一样,用户大多在需要时用new在堆上创建对象,且像Qt/GTK那样,父对象销毁后子指针失效,所有权由父对象持有。

解决方案

你的核心问题是直接将原始指针赋值给shared_ptr,导致每个Parent的shared_ptr都独立维护引用计数,销毁时会重复释放Child。以下是符合需求的实现方案:

1. 用std::enable_shared_from_this实现多父共享所有权

让Child继承std::enable_shared_from_this<Child>,这样所有Parent的shared_ptr会共享同一个引用计数,确保只有当所有持有Child的Parent都销毁后,Child才会被释放。修改后的代码如下:

#include <memory>
#include <vector>

class Child;

class Parent
{
public:
    // 支持多个Child的场景,用vector存储
    std::vector<std::shared_ptr<Child>> children;
    
    ~Parent() = default;
};

class Child : public std::enable_shared_from_this<Child>
{
    // 你的业务逻辑成员
public:
    void addToParent(Parent* parent)
    {
        parent->children.push_back(shared_from_this());
    }
};

// main函数示例
int main()
{
    Parent* prnt1 = new Parent();
    Parent* prnt2 = new Parent();
    
    // 用shared_ptr创建Child,确保所有权被正确管理
    std::shared_ptr<Child> chld = std::make_shared<Child>();
    // 用户可以保留原始指针,就像Qt的用法
    Child* raw_chld = chld.get();
    
    raw_chld->addToParent(prnt1);
    raw_chld->addToParent(prnt2);
    
    delete prnt1; // prnt1的shared_ptr被销毁,Child引用计数减1(剩余1)
    delete prnt2; // 引用计数归零,Child自动释放
    
    // 注意:用户不能手动delete raw_chld,否则会内存错误,需在库文档中明确说明
    return 0;
}

2. 实现类似Qt的指针失效感知

如果需要让用户感知Child是否已被销毁(避免野指针访问),可以让用户持有std::weak_ptr<Child>,使用前通过lock()获取有效的shared_ptr:

// 用户侧代码示例
std::weak_ptr<Child> weak_chld = chld;

// 后续使用时检查对象是否存活
if (auto valid_chld = weak_chld.lock()) {
    // 对象存活,安全操作
    // valid_chld->doSomething();
} else {
    // 对象已销毁,无法操作
}

3. 适配用户"用new创建对象"的习惯

如果用户习惯用new创建Child,可以封装一个工厂函数,内部用shared_ptr管理,同时返回原始指针给用户:

Child* createChild()
{
    auto ptr = std::make_shared<Child>();
    return ptr.get();
}

但必须明确告知用户:绝对不能手动delete这个原始指针,所有权完全由持有它的Parent管理,就像Qt中QObject的父对象管理机制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:44:52