0

ポインターを含むオブジェクトをデータメンバーとして追加するベクトルがあります。つまり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) ) );

       }

     }
4

2 に答える 2

2

あなたのコード:

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

非常に最適ではないように見えます。ロードに時間がかかるように見えるデータの不要なコピーが作成されます。つまり、このpngがロードされBlock::Block()ます。

あなたができる最善のことは、BlockVectorを次のようにすることです。

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

このようにして、Blockの不要なコピーを作成する必要はありません。それ以外の場合は、クラス内のSDL_Surface*ポインターに参照カウントを追加する必要があります。これは、カスタムdeleterを使用して行うこともできます(これについては、shared_ptrでdeleteを使用しないでください)。Blockshared_ptr

于 2012-10-15T23:57:17.837 に答える
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クラスには削除された(または未定義の)コピーコンストラクターが必要です。

于 2012-10-16T00:06:44.297 に答える