How to destroy a vector of pointers in C ++?

I have the following code in one of my methods:

vector<Base*> units; Base *a = new A(); Base *b = new B(); units.push_back(a); units.push_back(b); 

Should I destroy pointers a and b before exiting the method? Or should I just somehow destroy the vector of pointer units?

Change 1:

This is another interesting case:

 vector<Base*> units; A a; B b; units.push_back(&a); units.push_back(&b); 

How about this case? Now I do not need to use remote and smart pointers.

thanks

+4
source share
10 answers

If you exit the method, units will be destroyed automatically. But not a and b . Those who need to be clearly destroyed.

Alternatively, you can use std::shared_ptr for this if you have C ++ 11.

 std::vector<std::shared_ptr<Base>> units; 

And you just use the vector almost the same as before, but don’t worry about memory leaks when the function exists. I say almost because you need to use std::make_shared to assign to a vector.

+8
source

You need to iterate over the vector and delete each pointer that it contains. Deleting a vector will lead to a memory leak, because the objects pointed to by its elements are not deleted.

TL DR: objects remain, pointers get lost == memory leak.

+4
source

A pretty old-fashioned solution that works with all compilers:

 for ( vector<Base*>::iterator i = units.begin(); i != units.end(); ++i ) delete *i; 

In C ++ 11, this becomes as simple as:

 for ( auto p : units ) delete p; 

The second example does not require the release of a pointer; in fact, it would be a bad mistake to do this. However, this requires caution to ensure that a and b remain valid, at least as long as units do. For this reason, I would advise against this approach.

+4
source

Yes, you must destroy these pointers (assuming you are not returning the vector elsewhere).

You can easily do this with std :: for_each as follows:

 std::for_each( units.begin(), units.end(), []( Base* p ) { delete p; } ); 
+3
source

You should not delete if two situations coincide.

  • The created vector returns to the side of the function.
  • A vector created outside of a function, and presumably access to other functions.

In other situations, you must delete the memory indicated by the pointers in the vector. otherwise, after deleting the pointers, it is not possible to refer to these memory cells, and this causes a memory leak.

 vector<Base*>::iterator it; for ( it = units.begin(); it != units.end(); ){ delete * it; } 
+2
source

I would suggest that you use SmartPointers in a vector. Using smart pointers is a better practice than using raw pointers. You should use std :: unique_ptr, std :: shared_ptr or std :: weak_ptr smart pointers or boost equivalents if you don't have C ++ 11. The following is the documentation on acceleration for these smart pointers.

In the context of this question, yes, you should remove pointers added to the vector. Otherwise, it will lead to a memory leak.

+2
source

Yes and no. You do not need to delete them inside the function, but for other reasons than you might think.

You essentially transfer ownership of the objects to the vector, but the vector does not know about it, and therefore will not automatically call delete in pointers. Therefore, if you store your own pointers to objects in a vector, you must manually call delete on them for a while. But

  • If you pass a vector from your function, you should not destroy objects inside the function, or a vector full of pointers to freed memory will be pretty useless, so no. But in this case, you must make sure that the objects are destroyed after the vector has been used outside the function.
  • If you do not expose a vector from a function, you must destroy the objects inside the function, but there is no need to allocate them in free storage, so do not use pointers and new ones. You just click / place the objects directly into the vector, then it will take care of the destruction, and therefore you do not need to delete it.

And besides: Do not use a simple new one . Use smart pointers. No matter what you do with them, smart pointers will take care of the proper destruction of the contained objects. No need to use new, no need to use delete. Ever. (Except when you write your own low-level data structures, such as smart pointers). Therefore, if you want to have a vector full of pointers, these must be smart pointers. This way you do not have to worry about when and how to destroy objects and free up memory.

+1
source

You must delete them if you do not have a memory leak in the following code, if I comment on the two delete lines that the destructors never called, you must also declare the base class destuctor virtual. As mentioned above, it is better to use smart pointers.

 #include <iostream> #include <vector> class Base { public: virtual ~Base(){std::cout << "Base destructor" << std::endl;}; }; class Derived : public Base { ~Derived(){std::cout << "Derived destructor" << std::endl;}; }; int main() { std::vector<Base*> v; Base *p=new Base(); Base *p2=new Derived(); v.push_back(p); v.push_back(p2); delete v.at(0); delete v.at(1); }; 

Output:

 Base destructor Derived destructor Base destructor 

Exit with a non-virtual base destructor (memory leak):

 Base destructor Base destructor 
+1
source

The best way to store pointers in a vector would be to use smart_ptr instead of raw pointers. As soon as the DTOR vector is called and the control exits DTOR, all smart_ptrs will be counted. And you should never worry about memory leaks with smart_ptrs.

+1
source

In the first example, you will have to remove a and b , but not necessarily when units go beyond. You will usually do this just before units go out of scope, but this is not the only possible case. It depends on what is intended.
You can (later in the same function) an alias a or b , or both, because you want them to survive units or a scope of functions. You can put them in two unit objects at the same time. Or, many other possible things.

It is important that the destruction of the vector (automatic when the region is completed in this case) destroys the elements held by the vector, and nothing more. Elements are pointers, and killing a pointer does nothing. If you also want to destroy what the pointer points to (so as not to leak memory), you must do it manually ( for_each with lambda).
If you do not want to do this work explicitly, a smart pointer can automate this for you.

The second example (in the Edit1 section) does not require you to delete anything (in fact, this is not even possible, most likely you will see an attempt to do it), but this approach is probably harmful.

This code will work fine if you don’t refer to units anymore after a and b left pane. Woe, if so.

Technically, such a thing may even happen invisibly, since units destroyed after a , but, fortunately, ~vector does not look up pointer elements. It just destroys them, which does nothing for the pointer (trivial destructor).
But imagine that someone was so “smart” that they expanded the vector class, or maybe you will use this template in the future (because it “works fine”) with another object that does just that. Bang, you're dead. And you don’t even know where it came from.

What I really dislike about the code, even if it is strictly "legal", is the fact that it can lead to a condition that will lead to a failure or manifestation of a violation, irreproducible behavior. However, he is not immediately. The code that is “broken” should work immediately, so you see that something is wrong and you are forced to fix it. Unfortunately, this is not so.

It seems to work, perhaps for many years, until one day this happens. In the end, you forget that a and b live in the current frame of the stack and refer to non-existent objects in the vector from another place. Perhaps you are dynamically highlighting a vector in a future revision of your code, as you pass it to another function. And perhaps he will continue to work.
And then you will spend hours of your time (and probably others), trying to find out why a section of code that cannot fail leads to incorrect results or crashes.

+1
source

Source: https://habr.com/ru/post/1483298/


All Articles