繁体   English   中英

删除智能指针指向的对象

[英]Deleting objects pointed to by smart pointers

在我的代码中,我有一个SoundManager类,该类包含并处理游戏中的所有声音。 该类需要实例化,并且它的方法也被其他多个类调用。 但是,我希望只有一组声音会占用内存,因此为了提高效率,所有资产都声明为static shared_ptrs。

#include "SoundManager.h"

static shared_ptr<ISoundEngine> sEngine;

static shared_ptr<ISoundSource> hoverSound;
static shared_ptr<ISoundSource> confirmSound;
static shared_ptr<ISoundSource> mainBGM;
static shared_ptr<ISound> bgmInterface;

SoundManager::SoundManager(void)
{


//first we need to create the irrKlang sound engine instance
    if(!sEngine)
    {
        sEngine.reset(createIrrKlangDevice());
    }


    if(!hoverSound)hoverSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonHover.mp3"));
    if(!confirmSound)confirmSound.reset(sEngine->addSoundSourceFromFile("Sounds/ButtonConfirm.mp3"));
    if(!mainBGM)mainBGM.reset(sEngine->addSoundSourceFromFile("Sounds/mainBGM.mp3"));


    //set some default volumes
    hoverSound->setDefaultVolume(1.0f);
    confirmSound->setDefaultVolume(0.4f);
    mainBGM->setDefaultVolume(0.5f);


}


SoundManager::~SoundManager(void)
{   
}

在我的main()函数中实例化此SoundManager,并且每次我需要加载标题屏幕时(在此titlescreen类中也实例化SoundManager)。 一遍又一遍地初始化和销毁​​标题屏幕不会造成问题。 静态shared_ptrs对象不会被销毁,因为SoundManager的主要功能实例仍在使用它们。

现在,在运行我的游戏的实践中,这一切都很好。 但是,当涉及到干净退出时,当上面的静态对象被拆除时,会向我抛出未处理的运行时异常(访问冲突)。 VS2012的调试器将我指向memory.h中的一行。

private:
    virtual void _Destroy()
        {   // destroy managed resource
        delete _Ptr;       <<<<<<<<<The debugger points to this line
        }

我了解到,与obj-c相似,c ++ shared_ptrs使用引用计数器来确保在不存在任何需要使用它们的对象之前,不删除对象。 我不明白是什么原因导致这些错误。

也许我不应该忽略的重要部分:我的游戏是通过调用exit(0)退出的; 尽可能接近main()函数。 在执行此操作之前,我还没有采取任何措施来清理SoundManagers成员,因为我认为shared_ptr可以处理此问题。

有人知道什么可能导致我的清理问题吗?

如果要手动释放shared_ptr使用的资源,则需要调用reset 至于使用静态shared_ptr我不认为我的理由。 重点是它们不会复制资源,因此您将只有一个资源。

您正在使用IRRKLang库。 该库以预编译的二进制文件形式提供(如果您在Windows上,则为dll)。 该库通过使用纯虚拟库使其自身与二进制文件兼容。 这行得通,但是您不能像那样删除库的对象,因为您的程序new / delete与库的new / delete不同。 那些类型的库提供了一种分配内存的方法,这种情况下就属于这种情况。

要使用shared_ptr等,您必须使用自定义删除器。 看一下将自定义删除器与std :: shared_ptr一起使用,以了解如何进行操作并根据自己的需要对其进行修改。

就您而言,由于您使用的是Visual Studio 2012,因此您可以执行以下操作

template<class T>
struct IrrDeleter{
   void operator()(T* t){
       t->drop();
   }
};

然后更改所有重置行以包含删除器,例如

sEngine.reset(createIrrKlangDevice(),IrrDeleter<ISoundEngine>());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM