Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 处理自动资源释放的设计解决方案?_C++_Design Patterns_Resources - Fatal编程技术网

C++ 处理自动资源释放的设计解决方案?

C++ 处理自动资源释放的设计解决方案?,c++,design-patterns,resources,C++,Design Patterns,Resources,我是一名自学成才的新程序员,我的程序设计和结构一直存在问题。基本问题是在不破坏系统封装的情况下,释放通过API提供给我的资源(例如,必须使用glDeleteBuffers函数释放的OpenGL缓冲区等)。让我简单介绍一下我的设置: 首先,我的程序使用了一个名为“引擎”的大型“facade”类,其中包含一些用于图形渲染、音频流、事件处理等的子系统。我设计的主要思想之一是,每个子系统都将尽可能封装;OpenGL调用只存在于图形渲染系统中,OpenAL调用存在于音频中,等等 我还想小心资源分配和释放,

我是一名自学成才的新程序员,我的程序设计和结构一直存在问题。基本问题是在不破坏系统封装的情况下,释放通过API提供给我的资源(例如,必须使用glDeleteBuffers函数释放的OpenGL缓冲区等)。让我简单介绍一下我的设置:

首先,我的程序使用了一个名为“引擎”的大型“facade”类,其中包含一些用于图形渲染、音频流、事件处理等的子系统。我设计的主要思想之一是,每个子系统都将尽可能封装;OpenGL调用只存在于图形渲染系统中,OpenAL调用存在于音频中,等等

我还想小心资源分配和释放,因此我没有在程序的其他部分使用“new”创建各种资产(图像、声音等),而是在Engine类中设置了一些工厂方法来创建对象,向适当的子系统注册这些对象(例如,将图像对象引用发送到图形子系统,在图形子系统中可以对其进行适当的缓冲/注册到OpenGL),并返回指向这些对象的智能指针

class Engine     //..simplified for sake of example..//
{
private:
    GraphicsSystem graphicsRenderer;
    AudioSystem audioRenderer;
    //..window, events, etc...//

public:
    //ctors.. dtor.. tons of other methods..//

    std::shared_ptr<Image> createImage( /*filepath, size info, other params*/ );

    /*..both of these call equivalent graphics system functions:*/

    bool registerImage( Image & tempImage );    //allocates and registers texture resources..
    bool deregisterImage( Image & tempImage );  //frees those same resources upon object destruction..
};
Image类包含两个相同类型的指针,在我尝试传递指针之前,它起初看起来很好

std::shared_ptr<Image> Engine::createImage( std::string filePath )
{
    Image * tempImagePtr = new Image( filePath, &registerImage, &deregisterImage ); //create and send func ptrs..

    return std::shared_ptr<Image>( tempImagePtr ); //return..
}
什么都没用,语法太可怕了,几乎不值得费心

但是现在我觉得我又回到了原点;所以我一直在寻找其他的可能性。在我的头脑中,这个想法似乎非常简单:我只想让每个资产对象能够使用引擎对象注册和注销自己。

有没有更好/更简单的方法来实现我的目标,而不让每个资产访问整个引擎类接口?我已经读了一些关于的内容,这听起来可能是我想要的,但我不确定如何实现该模式,或者它是否真的是我需要的。当然,我也来了这些都能为我的问题提供解决方案吗


无论如何,谢谢你在这件事上对我直言不讳,我仍然只是在学习,我知道这对你们中的许多人来说可能是很简单的事情。如果还有什么我可以解释我想要什么或者我当前的系统正在使用什么,请让我知道,我会更新a.s.a.p.

这是一个有点高的水平,但看起来这就是你要去的舞台在你的设计中


出于某种原因,我认为您可能会从一个专门用于资源管理的类中受益。这个类将处理资源的创建和释放,它还可以提供一种重用资源的方法,比如资源池。

问题中有很多信息,我不确定我是否正确理解了所有这些信息,但我认为在这种情况下使用
共享的\u ptr
来处理RAII的原理听起来不错。如果我读对了,问题是您希望在最后一个
图像
引用发布时调用
引擎::注销图像()
,对吗

您是否尝试过为您的
共享\u ptr
使用自定义删除程序?如果您想在
图像
被销毁之前调用
引擎::注销图像()
,那么您需要某种方法将
引擎
实例绑定到共享指针。有很多方法可以做到这一点(lambdas,
std::bind
),但使用函子非常简单:

struct ImageDeleter
{
    Engine& engine;
    explicit ImageDeleter(Engine& e) : engine(e) {}

    void operator() (Image* img) {
        engine.deregisterImage(*img);
        delete img;
    }
};
然后在
Engine::createImage()
方法中,在
shared\u ptr
构造函数中注册删除程序:

return shared_ptr<Image>(tempImagePtr, ImageDeleter(*this));
returnshared_ptr(tempmageptr,ImageDeleter(*this));

现在,当最后一个引用被释放时,
shared\u ptr
将调用
ImageDeleter::operator()
,它应该都能工作。这要求您的
引擎
实例比它创建的所有图像都要长(否则您将留下一个悬空引用),但我想无论如何都会是这样。

太棒了!我还没有实现它,但它听起来正是我所需要的。我没有意识到我可以在共享指针中设置一个deleter函数!我感谢您的帮助,我将尝试使用functor。非常感谢Tristan!
&(this->registerImage)

&((*this).registerImage)
struct ImageDeleter
{
    Engine& engine;
    explicit ImageDeleter(Engine& e) : engine(e) {}

    void operator() (Image* img) {
        engine.deregisterImage(*img);
        delete img;
    }
};
return shared_ptr<Image>(tempImagePtr, ImageDeleter(*this));