std::shared_ptr _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 更改指针时
std::shared_ptr _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) when changing pointer
当这个函数运行时,我会得到sprite = spr;
行标题中描述的调试断言错误。如果我在此之前添加sprite.reset();
,它会在带有sprite.reset();
的行上崩溃。指针存储在static std::map<std::string,sf::Sprite> ResourceManager::sprites;
中的其他地方,所以我也不希望为sf::Sprite调用析构函数(尽管我怀疑这可能是因为它们存储在静态对象中…?)
VisibleGameObject.h
#ifndef VISIBLEGAMEOBJECT_H
#define VISIBLEGAMEOBJECT_H
#include "Game.h"
//just for keeping track of the sprite and drawing
class VisibleGameObject{
public:
VisibleGameObject(){}
VisibleGameObject(const std::string& name);
~VisibleGameObject();
std::string getTextureName();
void setSprite(const std::string& textureName);
void setSprite(const sf::Texture& texture);
void setSprite(std::shared_ptr<sf::Sprite> sprite);
void setPosition(float x,float y);
void setPosition(const sf::Vector2f& position);
void setRotationDegrees(float degrees);
void setRotationRadians(float radians);
float getRotationDegrees();
float getRotationRadians();
void setOrigin(float x,float y);
void setOrigin(const sf::Vector2f& origin);
sf::Vector2f getSize();
sf::Vector2f getOrigin();
sf::Vector2f getPosition();
std::shared_ptr<sf::Sprite> getSprite();
void draw(tgui::Window* wnd);
private:
std::string name;
std::shared_ptr<sf::Sprite> sprite;
std::string texture_name;
bool _loaded;
};
#endif
VisibleGameObject.cpp 摘录
//'sprite' is initialised here
void VisibleGameObject::setSprite(const std::string& textureName){
sprite = std::shared_ptr<sf::Sprite>(ResourceManager::createSpriteFromStoredTexture(textureName,name));
texture_name = textureName;
_loaded = true;
}
//error function!
void VisibleGameObject::setSprite(std::shared_ptr<sf::Sprite> spr){
sf::Vector2f p(0,0);
float d = 0;
if(_loaded){
p = spr->getPosition();
d = spr->getRotation();
}
sprite = spr;
sprite->setPosition(p);
sprite->setRotation(d);
_loaded = true;
}
摘录自ResourceManager.cpp
sf::Sprite* ResourceManager::createSpriteFromStoredTexture(const std::string& texturename,const std::string& spritename){
sf::Sprite spt;
spt.setTexture(*getTextureByName(texturename));
std::string name = spritename;
if(spritename == standard_spt_name){
name = spritename+std::to_string((long long)spritecount);
spritecount++;
}
sprites[name] = spt;
return &sprites[name];
}
VisibleGameObject在使用时似乎可以正常工作,而无需使用最初描述为问题的setSprite函数更改精灵。
您之所以失败,是因为您正在创建一个std::map<std::string,sf::Sprite>
,它实际上拥有"sf::Sprite"对象。然后给它一个指向std::shared_ptr<sf::Sprite>
映射中对象的指针,并使用默认的deleter。
这意味着,当对共享指针的最后一次引用超出范围时,它将对对象调用delete
。但是,该对象是地图的一部分。这会导致未定义的行为(在本例中为断言)。
有几个可能的解决方案:
1) 在这种情况下不要使用shared_ptr。由于sf::Sprite
的所有权始终与映射有关,因此您可以简单地不使用shared_ptr,而是使用普通指针。
2) 使用不执行任何操作的自定义删除程序。如果您有兴趣隐藏sf::Sprite
归映射所有的事实(比如说在某些情况下,您想动态创建它),那么,您需要创建一个null删除函数。这里我使用的是lambda,但您可以创建自己的函数。这会导致shared_ptr在最后一个引用超出范围时不执行任何操作。由于内存并不是真正由shared_ptr拥有的,所以这就是您想要的行为。
sprite = std::shared_ptr<sf::Sprite>(ResourceManager::createSpriteFromStoredTexture(textureName,name), [](const void*){} );
编辑:
事实上,我会修改第二个选项。与其返回原始指针,不如让createSpriteFromStoredTexture
方法返回shared_ptr,然后在其中使用noop deleter。这样,函数的用户就不知道sprite shared_ptr是如何创建的,只知道此时它有一个shared_ptr。
3) 使用shared_ptr<sf::Sprite>
的地图。地图将始终拥有精灵,但它使shared_ptr的使用更加自然。
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- C 字符串比较“祝您好运”&gt;“再见”
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- C 操作员&gt;&gt;与突变器过载
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 是否需要使用 - &gt;运算符在C 中调用成员函数时
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- 错误c++visual studio c2227左侧'->;Init';必须指向类/结构/联合/泛型类型
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- ``这个''不能用this-&gt;指针变量
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 调试断言失败 BLOCK_TYPE_IS_VALID (pHead->nblockuse) 从解构函数
- 使用shared_ptr<字符串>转换为一个无序集合<字符串>
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾