gpt4 book ai didi

c++ - std::shared_ptr _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 改变指针时

转载 作者:行者123 更新时间:2023-11-28 07:58:30 24 4
gpt4 key购买 nike

当此函数运行时,我收到调试断言错误,如 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 函数更改 sprite。

最佳答案

你失败了,因为你正在创建一个 std::map<std::string,sf::Sprite> ,它实际上拥有“sf::Sprite”对象。然后你给它一个指向 map 中对象的指针到 std::shared_ptr<sf::Sprite> ,并使用默认删除器。

这意味着当对共享指针的最后引用超出范围时,它将调用 delete在物体上。但是,该对象是 map 的一部分。这会导致未定义的行为(在本例中为断言)。

有几种可能的解决方案:

1) 在这种情况下不要使用 shared_ptr。自sf::Sprite的所有权|总是和 map 在一起,那么你就可以不用理会 shared_ptr 而是使用一个普通的指针。

2) 使用不执行任何操作的自定义删除器。如果您有兴趣隐藏 sf::Sprite 的事实由 map 拥有(假设在某些情况下您想动态创建它),然后,您需要创建一个空删除功能。我在这里使用的是 lambda,但您可以创建自己的函数。当最后一个引用超出范围时,这会导致 shared_ptr 不执行任何操作。由于内存并不真正归 shared_ptr 所有,这就是您想要的行为。

sprite = std::shared_ptr<sf::Sprite>(ResourceManager::createSpriteFromStoredTexture(textureName,name), [](const void*){} );

编辑:

实际上,我会修改第二个选项。我不会返回原始指针,而是 createSpriteFromStoredTexture方法返回 shared_ptr,然后在那里使用 noop 删除器。这样,该函数的用户就不知道 Sprite shared_ptr 是如何创建的,它只是知道此时它有一个 shared_ptr。

3) 使用 shared_ptr<sf::Sprite> 的 map . map 将始终拥有 Sprite ,但它使 shared_ptr 的使用更加自然。

关于c++ - std::shared_ptr _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 改变指针时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12114414/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com