我有一个类Block
,它在析构函数中调用SDL_FreeSurface(surface)
。在我创建Block实例的main()
中,对象正常运行,但当我在另一个Control
类中使用它时,vector<Block> block_vector
作为数据成员,程序崩溃了在Block
中添加block_vector
的实例。我在调用Block
时缩小了SDL_FreeSurface(surface)
的析构函数的问题。向向量添加对象是否与之有关?有什么问题?
class Block{
public:
Block(int x, int y);
~Block();
void Load_Image(MediaFunctions &M_Functions);
void SetPosition(int x, int y);
void BlitBlock(SDL_Event &event, MediaFunctions &M_Functions, SDL_Surface *destination);
bool DetectionNames(SDL_Event &event, MediaFunctions &M_Functions, SDL_Surface *destination);
bool DetectionHours(SDL_Event &event, MediaFunctions &M_Functions, SDL_Surface *destination);
bool return_error();
private:
SDL_Surface *block_surface_names;
SDL_Surface *block_surface_hours;
SDL_Surface *block_names_detected;
SDL_Surface *block_hours_detected;
SDL_Rect block_rect_names;
SDL_Rect block_rect_hours;
bool error;
};
//the problem
Block::~Block(){
SDL_FreeSurface(block_surface_hours);
SDL_FreeSurface(block_surface_names);
SDL_FreeSurface(block_hours_detected);
SDL_FreeSurface(block_names_detected);
}
//when doing this
void Control::HandleEvents(SDL_Event &event, MediaFunctions &M_Functions){
if(event.type == SDL_KEYDOWN){
if( event.key.keysym.sym == SDLK_a ){
//append a block instance
BlockVector.push_back(Block (Block(100,100)));
BlockVector.at(block_index).Load_Image(M_Functions);
block_index++;
}
}
}
答案 0 :(得分:3)
将一个Block对象插入向量时,会生成一个副本。由于您未提供复制构造函数,因此使用编译器生成的复制构造函数。编译器生成的复制构造函数将简单地复制指针。它不会复制实际的SDL表面。
这意味着您的原始Block对象和插入到向量中的Block对象都具有指向相同SDL表面的指针。当其中一个Block对象的生命周期结束时,将调用析构函数,从而释放SDL表面。现在另一个Block对象有一个悬空指针,当它的生命周期结束,并且调用析构函数时,你会在一个悬空指针上调用SDL_FreeSurface。
这几乎可以肯定是导致您崩溃的原因。这就是为什么你需要遵循Rule of Three,并正确实现复制构造函数和赋值运算符。实施取决于您。在大多数情况下,我建议您对对象进行完整,深入的复制。但是对于像SDL表面这样的重量级对象,我建议您考虑实现某种引用计数机制,或者使用std::shared_ptr
与自定义删除器一起调用SDL_FreeSurface
而不是delete
。< / p>