简体   繁体   English

C ++使用指针向Vector添加对象

[英]C++ Adding Objects with pointers into Vector

I have a vector that adds objects that contain SDL_Surface pointers as data members which means i have to use a copy constructor to implement a deep copy for the pointers. 我有一个向量添加包含SDL_Surface指针的对象作为数据成员,这意味着我必须使用复制构造函数来实现指针的深层复制。 The object frees the surfaces(pointers) in the destructor and this is where the problem occurs. 该对象释放析构函数中的表面(指针),这就是问题发生的地方。 At the moment the object is added into the vector(by pressing a button) the program crashes but when i take away the SDL_FreeSurface(surface) from the destructor(memory leak) the program doesnt crash when i add the object to the vector. 当对象被添加到向量中时(通过按下按钮)程序崩溃但是当我从析构函数中SDL_FreeSurface(surface) (内存泄漏)时,当我将对象添加到向量时程序不会崩溃。 How do I properly add the objects into the vector? 如何将对象正确添加到向量中? Some may think the problem is that the destructor is trying to delete dangling pointers but the error occurs upon the creation of the object in the vector. 有些人可能认为问题在于析构函数试图删除悬空指针,但是在向量中创建对象时会发生错误。

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

       }

     }

Your code: 你的代码:

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

looks very suboptimal, it creates unnecessary copies of data that looks like requires some time to load, I mean this png loading in Block::Block() . 看起来非常不理想,它会创建看似需要一些时间加载的不必要的数据副本,我的意思是在Block::Block()加载这个png。

The best what you can do is to make BlockVector to be: 您可以做的最好的事情是使BlockVector成为:

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

this way you wont need to make unnecessary copies of Block. 这样你就不需要制作不必要的Block副本了。 Otherwise you would need to add reference counting to your SDL_Surface* pointers in Block class, this can also be done with shared_ptr and custom deleter (for that look here: make shared_ptr not use delete ). 否则你需要在Block类中为你的SDL_Surface*指针添加引用计数,这也可以用shared_ptr和自定义删除器完成(在这里看看: make shared_ptr不能使用delete )。

Copy constructors should do deep copies, but yours doesn't. 复制构造函数应该进行深层复制,但是你的不是。 Luckily, you don't actually need a copy constructor at all, just a move constructor. 幸运的是,你根本不需要复制构造函数,只需要一个移动构造函数。

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

Only vaguely related to your issue: 只与你的问题含糊不清:

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

This makes a Block , then makes a copy of that Block , then pushes a copy of that block onto the vector. 这使得一个Block ,然后复制该Block ,然后将该块的副本推送到该向量上。 However, it's possible to simply make the Block directly in the vector, with this code: 但是,可以使用以下代码直接在向量中创建Block

BlockVector.emplace_back(100, 100, M_Functions);

If you don't have a C++11 enabled compiler, you're best off using a vector of boost::shared_ptr , which is slower and more complex than this code, but would also solve the problem. 如果你没有启用C ++ 11的编译器,你最好使用boost::shared_ptrvector ,它比这段代码更慢,更复杂,但也可以解决问题。 In either case, the Block class should have a deleted(or undefined) copy constructor. 在任何一种情况下, Block类都应该有一个已删除(或未定义)的复制构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM