2012-10-15 2 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 로딩을 의미한다.

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

당신이 늘 블록의 불필요한 복사본을 만들 필요가 이러한 방법 :

은 당신이 할 수있는 일은 BlockVector 될 수 있도록 최선이다. 그렇지 않으면 Block 클래스에있는 SDL_Surface* 포인터에 참조 카운팅을 추가해야합니다. shared_ptr 및 사용자 정의 삭제 프로그램 (여기에 대해서는 make shared_ptr not use delete)으로도 수행 할 수 있습니다.

+0

'shared_ptr'? 왜 그렇게 많은 오버 헤드를 추가하겠습니까? '블록 '을 움직일 수있는 방법을 보여주지 않겠습니까? –

+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을 할 수있다 : 당신이 C++ (11)를 사용할 수 컴파일러가없는 경우

BlockVector.emplace_back(100, 100, M_Functions); 

, 당신은 vectorboost::shared_ptr의를 사용하는 것이 가장 좋은 선택입니다, 이 코드보다 느리고 복잡하지만 문제를 해결할 수도 있습니다. 두 경우 모두 Block 클래스에는 삭제 된 (또는 정의되지 않은) 복사본 생성자가 있어야합니다.

+0

오브젝트를 벡터에 직접 두는 부정적인면은 무엇입니까? – starhacker

+0

@ Unit978 :'vector'에 더 많은 데이터를 삽입하면'Block'에 대한 포인터가 무효화 될 수 있지만'Block'과는 무관하게'vector'에 대한 일반적인 부정적 측면 만 유효합니다. 그 외에는 아무것도 없습니다. –

+0

* "문제를 해결하면 문제가 거의 해결됩니다."- 아닙니다. 그는 또한 들어오는 객체의 포인터를 null로해야합니다. –

관련 문제