2012-10-15 43 views
0

我有一个向量,添加包含SDL_Surface指针作为数据成员的对象,这意味着我必须使用复制构造函数来实现指针的深度复制。该对象释放析构函数中的曲面(指针),这是问题发生的地方。目前对象被添加到向量中(通过按下按钮)程序崩溃,但是当我从析构函数(内存泄漏)中拿走SDL_FreeSurface(surface)时,程序不会崩溃,当我将该对象添加到向量时。如何正确地将对象添加到矢量中?有些人可能会认为问题在于析构函数试图删除悬挂指针,但是在向量中创建对象时发生错误。C++添加指针到对象的对象

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))); 

     } 

    } 

回答

2

您的代码:

BlockVector.push_back(Block (Block(100,100, M_Functions))); 

看起来非常不理想的,它会创建一个看起来像数据的不必要的副本需要一些时间来加载,我的意思是在这个Block::Block()加载PNG。

最好的你可以做的就是让BlockVector是:

std::vector<boost::shared_ptr<Block>> blocks; 

这种方式,你不会需要做块不必要的副本。否则,您需要为Block类中的SDL_Surface*指针添加引用计数,这也可以使用shared_ptr和自定义删除程序(对于此处的看起来为make shared_ptr not use delete)完成。

+0

'shared_ptr'?为什么要添加那么多开销?为什么不告诉他如何让'Block'移动? –

+0

会有shared_ptr修复崩溃? – starhacker

+0

@MooingDuck是可移动的,这里是个好主意 – marcinj

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,你最好使用boost::shared_ptrvector,这比这个代码更慢更复杂,但也可以解决这个问题。无论哪种情况,Block类都应该有一个删除(或未定义)的拷贝构造函数。

+0

将对象直接放入向量中会有什么负面影响? – starhacker

+0

@单元978:只有在向量中插入更多数据时,只有'vector'的正常否定方面才会失效,但与'Block'无关。除此之外,什么都没有。 –

+0

*“,这几乎解决了这个问题”* - 不,它不。他还需要清空传入对象的指针。 –