[英]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.