共享指针导致奇怪的行为
Shared pointers causing weird behaviour
我在SFML 2.1中有以下代码
ResourceManager类:
shared_ptr<Sprite> ResourceManager::getSprite(string name) {
shared_ptr<Texture> texture(new Texture);
if(!texture->loadFromFile(resPath+spritesPath+name))
throw new NotSuchFileException();
shared_ptr<Sprite> sprite(new Sprite(*texture));
return sprite;
}
主方法:(我将省略大部分不相关的代码
shared_ptr<Sprite> sprite = ResourceManager::getSprite("sprite.png");
...
while(renderWindow.isOpen())
renderWindow.draw(*sprite);
奇怪的是,这会使我的精灵完全呈现白色,但如果我这样做:
shared_ptr<Sprite> ResourceManager::getSprite(string name) {
Texture* texture = new Texture; // <------- From shared pointer to pointer
if(!texture->loadFromFile(resPath+spritesPath+name))
throw new NotSuchFileException();
shared_ptr<Sprite> sprite(new Sprite(*texture));
return sprite;
}
效果很好。
这里发生了什么?我假设共享指针就像指针一样工作。会不会是它被删除了?我的主要方法是保持对它的引用所以我真的不明白这里发生了什么:S
编辑:我完全知道删除精灵不会删除纹理,这是产生一个内存泄漏,我必须处理,这就是为什么我试图使用智能指针在第一个地方…
我可能离得太远了,但我认为值得一试:
如果精灵类构造函数接受一个常规的纹理*或一个纹理引用(与它接受和存储一个共享指针相反),那么当shared_ptr超出getSprite的作用域时,纹理将被销毁(因为在该点之后没有shared_ptr的纹理存在)。
你在第一个中的共享指针超出了作用域并删除了对加载纹理的引用。为了保留该实例,您需要保存对sf::Texture实例的引用,因此您需要这样做(未经测试的代码):
std::map<std::string, std::unique_ptr<sf::Texture>> mLoadedTextures;
std::shared_ptr<sf::Sprite> ResourceManager::getSprite(std::string name) {
auto found = mLoadedTextures.find(name);
if (found == mLoadedTextures.end()) {
std::unique_ptr<sf::Texture> texture(new sf::Texture());
if (!texture->loadFromFile(resPath+spritesPath+name)) {
// ERROR: Unable to find/load texture
}
auto inserted = mLoadedTextures.insert(std::make_pair(name, std::move(texture)));
if (!inserted.second)) {
// ERROR: Unable to insert into map
}
found = inserted.first;
}
shared_ptr<sf::Sprite> sprite(new sf::Sprite(*found.second));
return sprite;
}
你应该重新考虑你的ResourceManager是如何运作的。理想情况下,你应该预先完成所有加载,并将所有纹理放在资源管理器拥有的地图中。这样,创建精灵就不会因为在"关键路径"上加载纹理而影响性能。
如果你读过"SFML游戏开发",他们会很好地涵盖这个主题。
http://www.packtpub.com/sfml-game-development/book对象的sf::Sprite
是相当轻量级的(它真的只是一个容器的四元和一些更多的信息),所以我甚至不会打扰他们在某种资源管理器管理。
更重的对象是纹理,所以只管理那一个。
如前所述,纹理的智能指针将超出作用域,因此纹理将被删除。
即使游戏中的每个实体都有自己的精灵,它也不会对性能造成太大影响(与重复使用一个精灵相比)。
所以,为了解决你的问题,管理纹理基于他们的路径,而不是精灵。
- 如何从具有移动语义的类对象中生成共享指针
- 使用共享指针的函数调用,其对象应为 const
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 如何访问由共享指针保存的类方法?
- 从矢量或地图中删除共享指针
- 使用共享指针时,从共享指针本身释放内存的机制是什么
- 使用共享指针实现复制 c'tor?
- C++/QT:使用指向私有成员的常量指针作为只读数据共享
- 共享指针继承,而不先显式强制转换
- 如何检查类中共享指针的有效性?
- 共享 C++ 的数据成员指针
- std::排序在共享指针的向量上
- 将相同共享指针的副本存储在不同的向量中是否是一种好的做法?
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- 嵌套类、继承和C++中的共享指针
- <Base> <Derived> 具有相同原始指针共享引用的 shared_ptr 和 shared_ptr 实例是否计数?
- 重载流<<运算符,用于指针/共享指针和其他类型的
- RAW指针共享_ptr
- 指针共享习语
- 将memmove函数与临时指针共享相同的地址