2012-10-15 44 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

*「,這幾乎解決了這個問題」* - 不,它不。他還需要清空傳入對象的指針。 –