我有一个向量添加包含SDL_Surface
指针作为数据成员的对象,这意味着我必须使用复制构造函数来实现指针的深层复制。该对象释放析构函数中的表面(指针),这就是问题发生的地方。当对象被添加到向量中时(通过按下按钮)程序崩溃但是当我从析构函数中取走SDL_FreeSurface(surface)
(内存泄漏)时,程序在向向量添加对象时不会崩溃。如何将对象正确添加到向量中?有些人可能认为问题在于析构函数试图删除悬空指针,但是在向量中创建对象时会发生错误。
class Block{
public:
Block(int x, int y, MediaFunctions &M_Functions);
Block(const Block& source);
~Block();
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;
};
////////////////////
Block::Block(int x, int y, MediaFunctions &M_Functions){
block_surface_names = M_Functions.LoadOptimizedImage("block_names.png");
block_surface_hours = M_Functions.LoadOptimizedImage("block_hours.png");
block_names_detected = M_Functions.LoadOptimizedImag("block_names_detected.png");
block_hours_detected = M_Functions.LoadOptimizedImag("block_hours_detected.png");
block_rect_names.x = x;
block_rect_names.y = y;
block_rect_names.w = block_surface_names -> w;
block_rect_names.h = block_surface_names -> h;
block_rect_hours.x = block_rect_names.x + block_rect_names.w;
block_rect_hours.y = block_rect_names.y;
block_rect_hours.w = block_surface_hours -> w;
block_rect_hours.h = block_surface_hours -> h;
}
//copy
Block::Block(const Block& source)
{
block_surface_names = source.block_surface_names;
block_surface_hours = source.block_surface_hours;
block_names_detected = source.block_names_detected;
block_hours_detected = source.block_hours_detected;
}
Block::~Block(){
//having this is necessary obviously- crashes program
//removing this causes the program not to crash
SDL_FreeSurface(block_surface_hours);
SDL_FreeSurface(block_surface_names);
SDL_FreeSurface(block_hours_detected);
SDL_FreeSurface(block_names_detected);
}
//where the object with SDL_FreeSurface() in the dtor is added to vector - crash!
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 using copy constructor
BlockVector.push_back(Block (Block(100,100, M_Functions) ) );
}
}
答案 0 :(得分:2)
您的代码:
BlockVector.push_back(Block (Block(100,100, M_Functions) ) );
看起来非常不理想,它会创建看似需要一些时间加载的不必要的数据副本,我的意思是Block::Block()
中的这个png加载。
您可以做的最好的事情是使BlockVector成为:
std::vector<boost::shared_ptr<Block>> blocks;
这样你就不需要制作不必要的Block副本了。否则,您需要为SDL_Surface*
课程中的Block
指针添加引用计数,这也可以使用shared_ptr
和自定义删除工具(在此处查看:make shared_ptr not use delete)
答案 1 :(得分:0)
复制构造函数应该进行深层复制,但是你的不复制。幸运的是,你根本不需要复制构造函数,只需要一个移动构造函数。
Block::Block(Block&& source)
{
block_surface_names = source.block_surface_names;
block_surface_hours = source.block_surface_hours;
source.block_surface_names = NULL;
source.block_surface_hour = NULL;
block_names_detected = source.block_names_detected;
block_hours_detected = source.block_hours_detected;
source.block_names_detected = NULL;
source.block_hours_detected = NULL;
}
只与你的问题含糊不清:
BlockVector.push_back(Block (Block(100,100, M_Functions) ) );
这会生成Block
,然后复制Block
,然后将 块的副本推送到矢量上。但是,可以使用以下代码直接在向量中创建Block
:
BlockVector.emplace_back(100, 100, M_Functions);
如果您没有启用C ++ 11的编译器,最好使用vector
boost::shared_ptr
,这比此代码更慢,更复杂,但也会解决问题。在任何一种情况下,Block
类都应该有一个已删除(或未定义)的复制构造函数。