Why do I need to remove pointers from a vector manually?

Why do I need to delete dynamically created elements in a vector manually? Why don't they remove them or call its destructor when the vector is deleted?

Usually something like this, but why do you need it?

vector<int*> v; for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it) { delete *it; } 
+4
source share
4 answers

First, you store the original pointers in your vector. These pointers are just pointers. They can point anywhere. They can point to local objects that cannot be deleted with delete . And even if they point to dynamically created objects, this does not necessarily mean that the user wants them to die with the vector. How should a vector know all this?

This is a matter of ownership of objects. The owner of the property is responsible for its proper and timely removal. Regular source pointers do not express ownership. This is why the vector cannot make any assumptions about whether to delete objects or not. If you want to tell the vector that it owns its dynamic objects, use the appropriate smart pointers.

Secondly, note that your removal method is not necessarily safe in the general case. Some standard containers assume that the data stored in them is always valid. When you delete for each vector element, the data in the vector becomes "invalid" (pointers become undefined). This is normal with a vector. But doing something like this in a β€œsmarter” container, for example, std::map or std::unordered_set , for example, may lead to problems. Even if you immediately destroy the container itself, it is quite possible that the algorithm for destroying the container may require analysis (comparison, hash, etc.) of the values ​​of individual elements. And you just killed them all with your cycle.

Reasonable pointers naturally resolve this issue. But if you need to use the delete guide for raw pointers stored in a standard container, then it would be better to follow these steps:

  • Get the value of an element in i and store it in the pointer p
  • Remove item from i from container
  • Do delete p

In the end, you will get an empty container and delete d data. Again, your approach will work for simple sequences like std::vector or std::list , but don't do this with ordered or hashed ones.

+10
source

Because the language does not know if you need them to stay alive when you are done. What if you inserted some pointers for the stack of objects or something like that? Boom.

However, this can be corrected using an intelligent pointer that will implement the appropriate policy for automatic destruction. unique_ptr and shared_ptr are the most common and useful.

+6
source

The destructor is not called because the pointer does not own the object it points to.

In C ++ 11, a std::unique_ptr<T> really belongs to the object it points to. In this case, the destructor is called when the pointer is released, which is probably the behavior you want. (If you do not have a C ++ 11 compiler, but have a fairly recent pre-C ++ 11 compiler, unique_ptr is still available as part of TR1.)

+3
source

The implementation of vector was done only to remove its memory. Pointers do not have deconstructors. And in C ++ there is no junk collection or logic to see that these are pointers and recursive delete it.

If you want to attend the next ISO meeting and suggest to be my guest, but for me I just put it in the inline function:

 template<class T> public static inline void deleteVectorPointer(std::vector<T*> v) { for (vector<T*>::iterator i = v.begin(); i != v.end(); i++) { delete *i; } } 
+1
source

All Articles