C++ 如何组织比对象所有者寿命短的类的对象所有权?

C++ 如何组织比对象所有者寿命短的类的对象所有权?,c++,pointers,memory-management,raii,ownership-semantics,C++,Pointers,Memory Management,Raii,Ownership Semantics,我有以下情况:存在GraphicsContext类: class GraphicsContext { ... private: std::unique_ptr<Renderer> m_renderer; } class Application { ... private: std::unique_ptr<GraphicsContext> m_graphicsContext; } 这样的子级别类在语义上并不拥有渲染器,因此我认为使用shar

我有以下情况:存在GraphicsContext类:

class GraphicsContext {
    ...
private:
    std::unique_ptr<Renderer> m_renderer;
}
class Application {
   ...
private:
    std::unique_ptr<GraphicsContext> m_graphicsContext;
}

这样的子级别类在语义上并不拥有渲染器,因此我认为使用shared_ptr而不是unique_ptr不是一个好主意。但是,如果保证子级别类的对象比应用程序对象的生存时间短,那么如何组织这种所有权呢?我可以从GraphicsContext存储并返回一个指向渲染器的原始指针,还是它的语义错误?

有一些方法可以解决这个问题

这些代码没有经过测试,但应该足以说明这个想法

解决方案1:明确跟踪 解决方案1A:-

class Renderer{
    std::vector<SubLevelClass*> whoThatLinkBackToMe; //or std::unordered_set
    public: ~Renderer(){
        //assert that whoThatLinkBackToMe.size() == 0
    }
};
class SubLevelClass{
    SubLevelClass(Renderer* renderer){
        renderer->whoThatLinkBackToMe.push_back(this);
    }
    //.. destructor should remove "this" from "renderer->whoThatLinkBackToMe" too
};
3.2每当要删除
渲染器时,只需将其
组件标记为\u CheckDelete::ToBeDeleted=true

然后,在时间步的末尾,检查
subvelClass
的每个实例
如果有一些
子级别类
引用了
呈现程序
,该呈现程序具有
convertToComponent(renderreptr)->ToBeDeleted==true
,则抛出断言失败

解决方案3 忽略整个问题。
这是用户方面的错误。引擎创建者不应该抓住每个用户的错误

Bullet Physics(最好的物理引擎之一)经常使用这种方法——如果我删除它的boardphase模块,仍然使用它的主引擎,我可能会得到不负责任的访问违规


我的观点:我通常选择解决方案3,有时选择解决方案2,很少选择解决方案1A。

std::shared\u ptr
是正确的解决方案

这样的子级别类在语义上并不拥有渲染器,因此我认为使用shared_ptr不是一个好主意


如果子级类需要延长
呈现程序的生存期以匹配它们自己的对象,那么它们共享它的所有权。

如果没有所有权问题,原始指针就可以了。可能的重复:François,但是与在这种情况下使用共享指针相比,它是否会导致内存泄漏?是否
subvelClass
delete
渲染器负责?我的理解是,不,永远不会。因此,一个原始指针是好的,您不必为它的生命周期负责。谁负责,谁就拥有像
std::unique\u ptr
这样的智能指针。如果可能有多个对象负责,则您拥有共享所有权,并在那里使用
shared\u ptr
。这里看起来,
渲染器
根本不涉及清理,所以不涉及所有权。但是可能我误解了你的问题。
子级别类
不负责
删除
渲染器。我指的是GraphicsContext决定在
子级别类中使用渲染器之前
删除它的情况。在本例中,我们将使用已经释放的指针。
class Renderer{
    std::vector<SubLevelClass*> whoThatLinkBackToMe; //or std::unordered_set
    public: ~Renderer(){
        //assert that whoThatLinkBackToMe.size() == 0
    }
};
class SubLevelClass{
    SubLevelClass(Renderer* renderer){
        renderer->whoThatLinkBackToMe.push_back(this);
    }
    //.. destructor should remove "this" from "renderer->whoThatLinkBackToMe" too
};
class CentralizeSystem{
    public: static std::unordered_map<Renderer*,SubLevelClass*> map;
};
class Renderer{
    public: ~Renderer(){
        //assert that CentralizeSystem::map[this].size() == 0
    }
};
class SubLevelClass{
    SubLevelClass(Renderer* renderer){
        CentralizeSystem::map.add(renderer,this);
    }
    //.. destructor should remove "this" from "CentralizeSystem::map" too
};
class Component_CheckDelete : public Component{
    public: bool ToBeDeleted=false;
};