ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 使用shared_ptr获得独特的所有权(种类) – 这是一种好的做法吗?

2019-10-02 21:07:26  阅读:234  来源: 互联网

标签:software-design c shared-ptr smart-pointers


这很难解释,但我会尽我所能.所以,我有一个RenderComponent,EventManager和RenderSystem.在我的RenderComponents构造函数中,我引发了RenderSystem订阅的renderComponentCreated事件.使用event args对象,我传递一个RenderNode作为数据,其中包含renderSystem绘制事物所需的信息(drawable,position和type).

到现在为止还挺好.现在,当删除renderComponent时,我希望RenderNode自动从RenderSystem中删除,同时仍然保留选项以手动删除它,例如作为对某些事件的反应.这可以使用RenderComponent订阅的RenderComponentRemoveNodeEvent来完成.

现在’问题’.根据我的理解(以及我想要的),renderNode应该是RenderComponent独有的东西(因此是unique_ptr).但是,这需要我复制(并为renderNode实现一个比较运算符 – >以便在我想删除它时能够找到它)或者将引用/原始指针传递给renderNode.但是,(如果我是正确的话)无法知道引用是否仍然引用了一个有效的对象,这意味着无法实现自动删除.

我的解决方案是使RenderNode(由RenderComponent独有拥有)共享并传递弱指针到事件. RenderSystem现在还维护一个弱指针列表,它检查它们是否仍指向有效对象,如果没有则自动删除它们.基本上我想要的是从一个独特的指针创建一个弱指针.但是,就像现在这样,有人可以从弱指针创建一个共享指针,并使RenderNode保持活动的时间超过应有的时间.由于托管对象本身(RenderNode)包含对不存在比RenderComponent更长的其他对象的引用,因此可能会导致严重问题.

我现在的问题是:这可以被认为是好的设计还是我错过了什么?

PS:对不起,如果这个解释有点笨重(英语不是我的母语),谢谢你的帮助!

解决方法:

使用std :: weak_ptr授予对可能被破坏的对象的访问权限肯定没有错,这就是它的发明.但它确实需要对象本身由std :: shared_ptr持有.这不仅掩盖了你的父对象生命周期控制的意图,它强制动态分配对象并阻止它成为父对象的成员变量.

另一种方法是通过句柄跟踪指针,并有一个句柄管理器来跟踪对象是活还是死.实现这一目标最安全的方法是使管理器成为您正在跟踪的对象的基类,这样RAII可以确保它始终是最新的.这是该概念的示例实现.注意:未经测试.

template<class Derived>
class HandleBased
{
public:
    typedef uint64_t handle_t;

    HandleBased() : m_Handle(NextHandle())
    {
        Map()[m_Handle] = this;
    }

    ~HandleBased()
    {
        auto it = Map().find(m_Handle);
        Map().erase(it);
    }

    handle_t ThisHandle()
    {
        return m_Handle;
    }

    static Derived* FindPtr(handle_t h)
    {
        auto it = Map().find(h);
        if (it == Map().end())
            return null_ptr;
        return static_cast<Derived*>(it->second);
    }

private:
    static handle_t NextHandle()
    {
        static handle_t next = 0;
        return next++;
    }

    static std::unordered_map<handle_t, HandleBased*>& Map()
    {
        static std::unordered_map<handle_t, HandleBased*> the_map;
        return the_map;
    }

    handle_t m_Handle;
};

以下是您如何使用它的示例:

class RenderNode : public HandleBased<RenderNode>
{
};

class RenderComponent
{
    std::unique_ptr<RenderNode> node1;
    RenderNode node2;

public:
    void Setup(RenderSystem& rs)
    {
        node1 = new RenderNode;
        rs.nodes.push_back(node1->ThisHandle());
        rs.nodes.push_back(node2.ThisHandle());
    }
};

class RenderSystem
{
public:
    std::list<RenderNode::Handle> nodes;

    void DoRender()
    {
        for (auto it = nodes.begin(); it != nodes.end(); )
        {
            RenderNode* p = RenderNode::FindPtr(*it);
            if (p == NULL)
                it = nodes.erase(it);
            else
            {
                p->DoSomething();
                ++it;
            }
        }
    }
};

标签:software-design,c,shared-ptr,smart-pointers
来源: https://codeday.me/bug/20191002/1844496.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有