简体   繁体   中英

Deleting objects from a vector of pointers

I have looked at a number of questions that are very similar but I still can't manage to fix this.

Consider the simple class:

class Obj
{
public:
    Obj(int moose);
    ~Obj();

private:
    int* val;
};


Obj::Obj(int num)
{
    val = new int;

    *val = num;
}


Obj::~Obj()
{
    printf("Cleanup");
    delete val;
}

Now I want to have a vector of pointers to objs. The source details the problem:

int main(int argc, const char * argv[])
{
    std::vector<Obj*> objs;

    Obj* o = new Obj(10);

    objs.push_back(o);

    objs.erase(objs.begin() + 0);

    // should have been deleted by now - I want the destructor to have been called
    // I have tried delete objs[0], casting to it and then deleting it.

    return 0;
}

The destructor in Obj is only called when the program has finished. I want it to be called when the object is erased from the vector.

Clarification: I am trying to delete the object using the reference from the vector. I cannot get it to do so. I know that the vector doesn't deallocate the memory. It just removes the reference from the vector. Can anyone provide code which would delete the object and call the destructor using a reference from the vector.

Edit:

Even after adding:

auto it = objs.begin() + 0;
delete *it;
objs.erase(it);

as suggested, the destructor of the Obj does not fire.

As a number of comments have pointed out, vector.erase only removes the elements from the vector. It does NOT try to delete any associated memory.
To delete the associated memory explicitly, you need to:

int main(int argc, const char * argv[])
{
    ...

    auto it = objs.begin() + i;
    delete *it;
    objs.erase(it);

}

Actually, in your case:

int main(int argc, const char * argv[])
{
    std::vector<Obj*> objs;

    Obj* o = new Obj(10);
    objs.push_back(o);    

    auto it = objs.begin();
    delete *it;
    objs.erase(it);

}

There are a number of other inconsistencies with your code and, better solutions for what you're trying to do, such as:

  • Using a vector<Obj> :

     int main(int argc, const char * argv[]) { std::vector<Obj> objs; objs.emplace_back(10); auto it = objs.begin(); objs.erase(it); } 
  • If you need to dynamically allocate your objects, but for some reason do not want the vector to handle that, you can use shared_ptr or unique_ptr , who will take care of the deallocation for you:

     int main(int argc, const char * argv[]) { std::vector<std::unique_ptr<Obj>> objs; objs.emplace_back(new Obj(10)); auto it = objs.begin(); objs.erase(it); } 

When you erase an element (which is a pointer) from a vector, you are just removing it from the container vector. But the location that the pointer was pointing to is still valid memory on heap. If you want to free that memory, you should use delete, and explicitly free the memory. If you do not want to manage the memory on your own, use smart pointers.

When you erase an item from a vector, the destructor of the item will be called. But in this case the item is a pointer, and pointers don't have destructors. The object the pointer is pointing to will not have its destructor called until you use delete on the pointer. If the pointer is erased and you don't have another copy of it, you'll never be able to delete it and you'll have a memory leak.

Whenever possible, prefer to put the object itself in the vector rather than a pointer. That will relieve you of the chore of memory management.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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