What do I need to do before deleting elements in a vector of pointers to dynamically allocated objects?
- Yes
- Vectors are implemented using template memory allocators that take care of the memory management for you, so they are somewhat special. But as a general rule of thumb, you don't have to call
delete
on variables that aren't declared with thenew
keyword because of the difference between stack and heap allocation. If stuff is allocated on the heap, it must be deleted (freed) to prevent memory leaks. - No. You explicitly have to call
delete myVec[index]
as you iterate over all elements.
Ex:
for(int i = 0; i < myVec.size(); ++i)
delete myVec[i];
With that said, if you're planning on storing pointers in a vector, I strongly suggest using boost::ptr_vector
which automatically takes care of the deletion.
clearing a vector of pointers
Yes, the code has a memory leak unless you delete the pointers. If the foo
class owns the pointers, it is its responsibility to delete them. You should do this before clearing the vector, otherwise you lose the handle to the memory you need to de-allocate.
for (auto p : v)
{
delete p;
}
v.clear();
You could avoid the memory management issue altogether by using a std::vector
of a suitable smart pointer.
How to properly clean up elements from vectors of object pointers
you mentioned in the comments that the objects will have other pointers to them. this sounds like std::shared_ptr<A>
to me. this way you can have other pointers to your A
objects without memory leaking issues. (std::shared_ptr
comes with a small(!) performance cost, but you should not worry about it for now).
additionally i changed your passage to delete/erase your element from the vector. be aware that the A
objects are still alive IF there are other instances keeping a std::shared_ptr<A>
copy to it (but thats a good thing).
here is the code:
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class A
{
public:
A(int i) { x = i; }
int x;
};
int main()
{
std::vector<std::shared_ptr<A>> Vec;
Vec.emplace_back(std::make_shared<A>(5));
Vec.emplace_back(std::make_shared<A>(4));
Vec.emplace_back(std::make_shared<A>(3));
std::cout << "Size before = " << Vec.size() << std::endl;
Vec.erase(
std::remove_if(std::begin(Vec),std::end(Vec), [](auto&& ptr){ return ptr->x == 3;}),
std::end(Vec));
std::cout << "Size after = " << Vec.size() << std::endl;
for (auto&& a : Vec)
{
std::cout << a->x << std::endl;
}
return 0;
}
If I call delete on a pointer to a vector std::vectorObject**, will the elements be deleted as well?
No, and here's why.
Consider these two cases:
int a, b, c;
auto stackvec = new vector<int*> { &a, &b, &c };
auto heapvec = new vector<int*> { new int, new int, new int };
delete stackvec;
delete heapvec;
If calling delete
on the vector*
s called delete
on the pointers they hold, then you'd be in for a heap of trouble (pun intended) because you'd be delete
ing automatic variables with the first delete
which yields undefined behaviour (a bad thing).
You have to manually iterate the vector
and delete
the pointers yourself when you know they're dynamically allocated, or better, use std::unique_ptr
and you never need to call delete
on anything.
Also, you probably don't need a pointer to a vector
in the first place, but I won't judge you since I don't know your situation.
As for std::array
and std::vector
, you need to know the size of your std::array
at compile time and you can't resize it at runtime, but vector
has neither of those restrictions.
How do I destruct a dynamically allocated array of dynamic object?
Is it necessary to delete all the objects in the destructor of vector? like this
Technically yes but what if you want a vector of pointers that does not represent ownership? You could easily end up either double-deleting an object, or trying to delete a stack-based object:
obj obj_a;
obj* obj_b = new obj;
vector<obj*> obj_ptrs;
obj_ptrs.elem[0] = &obj_a;
obj_ptrs.elem[1] = &obj_a;
obj_ptrs.elem[2] = obj_b;
delete obj_b;
Whether the pointed objects need to be deleted with the vector is none of the vector's business.
The cleanest way to address that is to use std::unique_ptr
, which is an object type that holds a pointer and deletes it when it gets destroyed:
#include <memory>
template <typename T> struct vector {
// ...
~vector() {
// The vector is only responsible for deleting the array.
delete[] elem;
}
};
// ...
void foo() {
vector<std::unique_ptr<obj>> obj_ptrs;
obj_ptrs.elem[0] = std::make_unique<obj>();
obj_ptrs.elem[1] = std::make_unique<obj>();
obj_ptrs.elem[2] = std::make_unique<obj>();
obj stack_obj;
vector<obj*> obj_no_own_ptrs;
obj_no_own_ptrs.elem[0] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[1] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[2] = &stack_obj;
// Everything gets deleted
// No double-delete concern
}
Why vector does not call destructor of pointers on clearing?
Containers only own the elements they directly contain - in this case the pointers. They do not own the pointees of these pointers and are thus not obliged (or even allowed) to destroy them.
You can use a vector
of unique_ptr
s:
std::vector<std::unique_ptr<foo>> vec;
vec.emplace_back( new foo );
unique_ptr
s own their pointees, and thus the vector
who contains and owns the unique_ptr
s subsequently also owns their pointees, and will destroy them implicitly when destroying the elements (e.g. when going out of scope).
Also have a look at Boosts Pointer Container Library, specifically boost::ptr_vector
.
boost::ptr_vector<foo> vec;
vec.push_back( new foo );
// the object is automatically destroyed
How to delete objects from vector of pointers to object?
Only call delete on variables that were created with new
Check this link:
Calling delete on variable allocated on the stack
Related Topics
Is There C/C++ Equivalent of Eval("Function(Arg1, Arg2)")
The C 'Clock()' Function Just Returns a Zero
C++ Comparison of Two Double Values Not Working Properly
How to Extract the Mantissa of a Double
Math Precision Requirements of C and C++ Standard
How to Create a Type in C++ That Takes Less Than One Byte of Memory
Do All Virtual Functions Need to Be Implemented in Derived Classes
Wrapping C++ Class API for C Consumption
Portable Zip Library for C/C++ (Not an Application)
Is It Bad Practice to Allocate Memory in a Dll and Give a Pointer to It to a Client App
Convert a Unicode String in C++ to Upper Case
What Is the Use of 0-Length Array (Or Std::Array)
How to Include Compiler Flags in Visual Studio Code
Using Sfinae to Check for Global Operator<<
Is a Logical Right Shift by a Power of 2 Faster in Avr
What Operators Do I Have to Overload to See All Operations When Passing an Object to a Function