I am storing dynamically allocated class pointers in a vector like below.
vector<Test *> v;
Test *t1 = new Test;
Test *t2 = new Test;
v.push_back(t1);
v.push_back(t2);
Now, if i have to free Test objects, i have to loop through entire vector and free one by one and then do a clear.
for(int i = 0; i<v.size(); i++)
{
delete v[i];
}
v.clear();
Is there any function in vector to free all internal objects. That function should call Test class destructor for each object.
I understand that it is difficult for Vector class whether the pointer is address of a local object or dynamically allocated.
But still, whenever developer is confident that all are dynamically allocated he could have used freeing function if provided.
Although vector is treated as advanced Array, freeing objects in an array is much easier like below.
Test *a = new Test[2];
delete []a;
Is there any function in vector to free all internal objects ?
Your examples don't do the same thing at all.
If you want the vector equivalent of this array code:
Test *a = new Test[2];
delete []a;
it is simply
std::vector<Test> a(2);
If you have a vector of pointers to dynamically allocated objects, you need to delete every one of them, as in your example:
for(int i = 0; i<v.size(); i++)
{
delete v[i];
}
but the same thing is true for an array:
Test *t1 = new Test;
Test *t2 = new Test;
Test **a = new Test*[2];
a[0] = t1;
a[1] = t2;
also has to be deleted with such a loop:
for(int i = 0; i<2; i++)
{
delete a[i];
}
delete[] a;
In the first case, you have two objects stored in a container of some sort. That container may be a vector, or it may be an array.
In both cases, because the objects are stored directly in the container, their destructors are called when the container is destroyed. You don't need to do anything to destroy or delete individual members, you just have to destroy the container (which is simpler with the stack-allocated vector, where you don't even need to call delete[])
But if your container stores pointers to dynamically allocated objects, then it is your responsibility to delete those objects at some point. And that is true whether your container is an array or a vector.
No, there is no way to request that a std::vector full of pointers automatically call delete on all of its elements.
There are, however, other, third-party containers that will make this sort of thing easier by automatically deleting pointers when they are removed from the vector, or when the vector destructs. For example, boost::ptr_vector and friends.
The short answer is no. C++ does not provide a vector of pointers free'ing function.
The long answer is twofold:
Use smart pointers, and forget about free'ing (there's shared_ptr or unique_ptr in c++0x that will serve most of your needs). Alternatively, use a Boost ptr_vector like Tyler suggested.
It's not that hard to write a simple generic algorithm to delete each item in a container (use a template with iterators).
(warning: untested code, have no time to check it)
template<class It>
void delete_clear_ptr_cont( const It &beginIt, const It &endIt )
{
for( auto it = beginIt; it != endIt; ++it )
{
delete it;
}
erase( beginIt, endIt );
}
No, vector isn't aware that it may be instantiated with pointers. And even if it was, there are situations where you don't own the pointers and you don't want the delete behavior.
In most cases we simply use a vector of smart pointers, like shared_ptr. However, there are times where shared_ptr isn't appropriate. For those cases we have a functor in our toolbox like this:
#include <functional>
template<typename T>
struct PointerDelete : public std::unary_function<T*, T*>
{
T* operator()(T*& p) const
{
delete p;
return 0;
}
};
Then, assuming you have a vector<Foo*>, you could do either:
#include <algorithm>
std::for_each(v.begin(), v.end(), PointerDelete<Foo>());
// or
std::transform(v.begin(), v.end(), v.begin(), PointerDelete<Foo>());
If you can use the boost library, there are also ptr_containers, which are containers that take ownership of pointers and do the delete for you automatically on container destruction.
I asked the same question before and I was suggested to use Boost library and you will find great tips
here or simply you can understand smart pointers as follows :
Instead of having a vector of pointers you will have a vector of smart pointers , as for each new you will make it will delete itself without you having to worry .
Related
I'm in a case where i use a builder to use factory to create CombatUnit for my project, as show in the schema (please note that I have an abstract factory, but i wouldn't complexify it for nothing).
The thing is, i'm creating arrays of arrays and i'm using unique_ptr to protect from memory leaks.
But i can't find if i'm overusing smart_pointer for nothing, here why
std::unique_ptr<std::vector<std::unique_ptr<std::vector<std::unique_ptr<CombatObject>>>>>& Builder_FleetsCombatObjects::BuildFleets(const std::vector<const CombatObject::ConstructionOrder_CombatObject>& orders)
{
std::unique_ptr<std::vector<std::unique_ptr<std::vector<std::unique_ptr<CombatObject>>>>> fleets(new std::vector<std::unique_ptr<std::vector<std::unique_ptr<CombatObject>>>>());
Factory_Mechas mFact;
Factory_SpaceShip sFact;
for (auto order : orders)/* No Abstract factory to match schema */
{
if (sFact.IsMine(order.TypeOfObjectToBuild) != false)
{
fleets->push_back(sFact.CreateSpaceShip(order));
}
else if (mFact.IsMine(order.TypeOfObjectToBuild) != false)
{
fleets->push_back(mFact.CreateMechas(order));
}
}
return fleets;
}
From my actual perspective it's not overdoing it, even if smart_pointer are heavier and slower (in general use i mean), each unique_ptr will make sure that the sub smart_pointer "deleter" will be called.
But somehow i can't feel it's right, like i'm not understanding well how smartpointer work.
Shouldn't vector "make sure" sub vector are "free"? then i could reduce to : std::unique_ptr<std::vector<std::vector<std::unique_ptr<CombatObject>>>>&
Or even std::vector<std::vector<std::unique_ptr<CombatObject>>> if vector are memory managed in c++19.
I'm not sure of what i understand, can you help me?
C++ is Unique_ptr pertinent for vectors of vectors
That's for you to decide, but only rapidly looking at the code without other knowledge of the infrastructure, I would say that this is a heavy, terrible code smell. I would simply use the vector as is. It's lighter, safer, simpler, and faster.
A pointer to a STL containe is usually a strong indicator of code smell, and a pointer to a STL container that contains pointer to STL containers has even a stronger code smell. This would simply not pass review and I would urge to simplify.
Owning pointers to STL containers should practically not exist in a code, unless there is some class that encapsulate very special memory management through container pointers, but they should not escape that class. And even then, you can manage memory and reuse with simple container values.
You should give value semantics a try! It helps local thinking and usually make code simpler.
Now for the non opinion based part of the question.
Let's drop the superfluous unique pointers in your code so it's easier to explain:
std::vector<std::vector<std::unique_ptr<CombatObject>>>& Builder_FleetsCombatObjects::BuildFleets(const std::vector<const CombatObject::ConstructionOrder_CombatObject>& orders)
{
std::vector<std::vector<std::unique_ptr<CombatObject>>> fleets{};
Factory_Mechas mFact;
Factory_SpaceShip sFact;
for (auto order : orders)/* No Abstract factory to match schema */
{
if (sFact.IsMine(order.TypeOfObjectToBuild) != false)
{
fleets.push_back(sFact.CreateSpaceShip(order));
}
else if (mFact.IsMine(order.TypeOfObjectToBuild) != false)
{
fleets.push_back(mFact.CreateMechas(order));
}
}
return fleets;
}
In this code, we copy and construct new vectors, and also allocate new unique pointers.
Here, your question would become: How to make sure a vector of vector of unique pointer is freed?
Well, let's start by looking at a vector of integer:
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
}
// Did we leaked?
Here, we did not leaked. This is because the vector is responsible to allocate, and also deallocate. It will deallocate old buffers when pushing back, and will deallocate when the vector goes out of scope.
Now what about a unique pointer?
{
std::unique_ptr<int> ptr = std::make_unique<int>(3);
*ptr = 1;
} // Did we leaked?
Now did we leaked? No. That would be quite absurd!
Now let's try copying these two types:
std::vector<int> vec;
std::unique_ptr<int> ptr = std::make_unique<int>(3);
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
// Copy!
std::vector<int> vec2 = vec;
std::unique_ptr<int> ptr2 = ptr; // Uh oh! Error!
Here as you can see, you cannot copy the unique pointer. Copying a unique pointer won't compile.
However, you can copy a vector, so what's happening when you copy a vector of unique pointer?
std::vector<std::unique_ptr<int>> vec_ptr;
vec_ptr.push_back(std::make_unique<int>(1));
vec_ptr.push_back(std::make_unique<int>(2));
vec_ptr.push_back(std::make_unique<int>(3));
std::vector<std::unique_ptr<int>> vec_ptr2 = vec_ptr; // Error again!
Here it still won't compile! That is because to create a copy of the buffer, you need to copy each elements. If the elements cannot be copied, you cannot copy the vector, so the vector is not copiable.
Now since a vector manage the memory completely, and that unique ptr manages the memory completely, you cannot leak any memory unless you explicitly ask the unique pointer to drop ownership:
std::unique_ptr<int> ptr = std::make_unique<int>(3);
int* raw_owning_pointer = ptr.release();
// Here, I have to delete it myself
Now in your code, no matter the push backs and the unique pointer and vector combination, there is no leak!
To be really sure that there is no leak at all, use a sanitizer, or a memory debugger such as valgrind.
vector<char*> x;
I have many vectors in my code. However, I need to delete them to minimize memory usage. I know there is a solution like using a "shared_array" but I am not permitted to import any other library. Is there any good solution to prevent memory leak after using vectors?
In your code snippet, you are using a vector of char pointers. I assume that those pointers are allocated via new, and they need to be freed via delete. If the vector goes out of scope, it will be freed, but all those char arrays won't get freed. You need to free them manually.
An alternative would be to use std::string, specifically vector<std::string>. In this way, when the vector goes out of scope, all the strings will be automatically deleted.
C++11 has support for smart pointer objects, such as shared_ptr, so you don't have to use Boost (or anything else).
As johnathon said, you can then just wrap the char * with a smart pointer et voilà, you don't have to worry about it anymore.
std::vector<std::unique_ptr<char*>> x;
or
std::vector<std::shared_ptr<char*>> x;
When the element is removed from the vector in either way (.delete(), .erase(), ...) or simply when vector is destroyed, you buffers will be freed.
If your STL implementation or compiler does not support this C++11 feature yet, you can also roll your own smart pointer type, it shouldn't be too hard. See for example this tutorial.
You may use
//Create
vector<char*>* _vec = new vector<char*>(5);
//Fill with something
for(unsigned int i=0; i<_vec->size(); ++i)
(*_vec)[i] = new char[100];
....
//Delete
for(unsigned int i=0; i<_vec->size(); ++i)
delete[] (*_vec)[i]; //Deleting array of char
delete _vec; //but not delete[] as we deleting only one instance of vector
Consider the following example:
#include <vector>
class Foo {
std::vector<int*> v;
public:
Foo() {
this->v.push_back(new int(23));
this->v.push_back(new int(24));
this->v.push_back(new int(25));
}
~Foo() {
}
};
int main() {
Foo f;
return 0;
}
When f goes out of scope in main(), f's destructor is called, which should indirectly free f.v. According to this, the destructor of each element of the vector v should now be called.
However, when I run this program in valgrind, I find that the int*'s were not deallocated.
$ valgrind --leak-check=full ./a.out
What am I missing here?
std::vector<T> does indeed call the destructor of T when it is destroyed. Here T is int *. The destructor of int * does nothing. The storage for the int * itself is freed, but the ints they point to are not.
Consider:
int main() {
int *x = new int(23);
return 0;
}
This exhibits the same problem; when x goes out of scope, its destructor is indeed called, and the storage for the pointer that is x is freed, but since the destructor of a pointer is a no-op, the pointed-to int is not freed.
More to the point, vector doesn't know how the ints were allocated. They might be allocated by new int, but they could also point to elements inside an array allocated with new int[200], or they might point to malloc'd data, or they might point into a mmap'd buffer, or they might point to struct elements, or two vectors might be pointing to the same ints... etc. vector isn't smart enough to divine what you want done with these, and so it leaves them alone (additionally, giving vector logic to delete pointed-to elements would break vectors of non-pointer elements such as std::vector<int>, as you can't delete an int!)
You need to either use a std::vector<int>, or use a smart pointer in conjunction with it, eg std::vector<boost::shared_ptr<int> >. Note that using smart pointers may add overhead; with C++0x you should be able to use std::vector<std::unique_ptr<int>> in conjunction with std::move to avoid this overhead. Boost also has pointer vectors that free the pointed-to elements as you expected as well.
The destructor of each element of the vector v should now be called
Yes: the int* objects stored in the vector are destroyed (which is effectively a no-op). The objects pointed to by the pointers in the container are not destroyed.
Consider the following, equally valid program:
{
int x;
std::vector<int*> v;
v.push_back(&x);
} // x cannot be delete'd because it isn't dynamically allocated.
You should use a smart pointer, like std::unique_ptr or shared_ptr so that you don't have to worry about the memory management (do not use std::auto_ptr; it is incompatible with the Standard Library containers because it isn't really copyable). If you don't use a smart pointer then you need to destroy the dynamically objects yourself; doing this correctly is rather difficult.
Each element of your vector is an int *. When an int * is destroyed, the language does not automatically call delete on it. In other words, it's the pointer being destroyed, not the pointee.
Since you are using the new keyword, the integers are being allocated on the heap rather than the stack. In other words, they are being allocated dynamically. In other words, you need to clean up after it.
The "destructor" for a pointer type is to simply delete that pointer. It does not touch the data which is located at the memory address stored by the pointer. Consider the following example:
int a = 5;
int* i = &a;
if (true)
{
int* j = i;
} //j goes out of scope, should *i and a be deleted? no.
So you will need to do this in the destructor:
std::vector<int*>::iterator iter;
for (iter = v.begin(); iter != v.end(); iter++)
{
delete *iter;
}
I have a vector that I fill with pointers to objects. I am trying to learn good memory management, and have a few general questions:
Is it true that when I am done with the vector, I must loop through it and call delete on each pointer?
Why don't I have to call delete on the vector or any other variable I declare without the new statement, but delete must be called on pointers?
Does C++ handle freeing the pointers' memory for me if the vector is declared in a function which returns (causing the vector to go out of scope)?
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 the new 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.
Is it true that when I am done with the vector I must loop through it and call delete on each pointer?
Well, you don't have to loop by hand, you can also use an algorithm:
#include <vector>
#include <algorithm>
#include <memory>
int main()
{
std::vector<Base*> vec;
vec.push_back(new Derived());
vec.push_back(new Derived());
vec.push_back(new Derived());
// ...
std::for_each(vec.begin(), vec.end(), std::default_delete<Base>());
}
If you don't have a C++0x compiler, you can use boost:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/construct.hpp>
std::for_each(vec.begin(), vec.end(), boost::lambda::delete_ptr());
Or you can write your own functor:
struct delete_ptr
{
template <class T>
void operator()(T* p)
{
delete p;
}
};
std::for_each(vec.begin(), vec.end(), delete_ptr());
You can also use std::unique_ptr if you have access to C++0x. It replaces the deprecated std::auto_ptr that couldn't be used in containers.
Everything you allocate with new you have to delete later on. Objects that you don't explicitly allocate with new shouldn't you delete.
If you don't want to manage the objects manually but want the vector to "own" them, it might be better to store the objects by value instead of storing pointers to them. So instead of std::vector<SomeClass*> you could use std::vector<SomeClass>.
As an alternative to boost::ptr_vector as mentioned by David Titarenco, you can easily modify std::vector to automatically free memory for containing pointers on deletion:
template<class T>
class Group : public std::vector<T>
{
public:
virtual ~Group() {};
};
template<class T>
class Group<T *> : public std::vector<T *>
{
public:
virtual ~Group()
{
std::vector<T *>::reverse_iterator it;
for (it = this->rbegin(); it != this->rend(); ++it)
delete *it;
}
};
All functionality provided by std::vector is inherited so you would add items the same way:
Group<Foo *> *bar = new Group<Foo *>();
bar->push_back(new Foo());
bar->push_back(new DerivedFoo());
// Deleting the Group will free all memory allocated by contained pointers
delete bar;
How does container object like vector in stl get destroyed even though they are created in heap?
EDIT
If the container holds pointers then how to destroy those pointer objects
An STL container of pointer will NOT clean up the data pointed at. It will only clean up the space holding the pointer. If you want the vector to clean up pointer data you need to use some kind of smart pointer implementation:
{
std::vector<SomeClass*> v1;
v1.push_back(new SomeClass());
std::vector<boost::shared_ptr<SomeClass> > v2;
boost::shared_ptr<SomeClass> obj(new SomeClass);
v2.push_back(obj);
}
When that scope ends both vectors will free their internal arrays. v1 will leak the SomeClass that was created since only the pointer to it is in the array. v2 will not leak any data.
If you have a vector<T*>, your code needs to delete those pointers before delete'ing the vector: otherwise, that memory is leaked.
Know that C++ doesn't do garbage collection, here is an example of why (appologies for syntax errors, it has been a while since I've written C++):
typedef vector<T*> vt;
⋮
vt *vt1 = new vt, *vt2 = new vt;
T* t = new T;
vt1.push_back(t);
vt2.push_back(t);
⋮
delete vt1;
The last line (delete vt1;) clearly should not delete the pointer it contains; after all, it's also in vt2. So it doesn't. And neither will the delete of vt2.
(If you want a vector type that deletes pointers on destroy, such a type can of course be written. Probably has been. But beware of delete'ing pointers that someone else is still holding a copy of.)
When a vector goes out of scope, the compiler issues a call to its destructor which in turn frees the allocated memory on the heap.
This is somewhat of a misnomer. A vector, as with most STL containers, consists of 2 logical parts.
the vector instance
the actual underlying array implementation
While configurable, #2 almost always lives on the heap. #1 however can live on either the stack or heap, it just depends on how it's allocated. For instance
void foo() {
vector<int> v;
v.push_back(42);
}
In this case part #1 lives on the stack.
Now how does #2 get destroyed? When a the first part of a vector is destroyed it will destroy the second part as well. This is done by deleting the underlying array inside the destructor of the vector class.
If you store pointers in STL container classes you need to manually delete them before the object gets destroyed. This can be done by looping through the whole container and deleting each item, or by using some kind of smart pointer class. However do not use auto_ptr as that just does not work with containers at all.
A good side effect of this is that you can keep multiple containers of pointers in your program but only have those objects owned by one of those containers, and you only need to clean up that one container.
The easiest way to delete the pointers would be to do:
for (ContainerType::iterator it(container.begin()); it != container.end(); ++it)
{
delete (*it);
}
Use either smart pointers inside of the vector, or use boost's ptr_vector. It will automatically free up the allocated objects inside of it. There are also maps, sets, etc.
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_vector.html
and the main site:
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_container.html
As with any other object in the heap, it must be destroyed manually (with delete).
To answer your first question:
There's nothing special about STL classes (I hope). They function exactly like other template classes. Thus, they are not automatically destroyed if allocated on the heap, because C++ has no garbage collection on them (unless you tell it to with some fancy autoptr business or something). If you allocate it on the stack (without new) it will most likely be managed by C++ automatically.
For your second question, here's a very simple ArrayOfTen class to demonstrate the basics of typical memory management in C++:
/* Holds ten Objects. */
class ArrayOfTen {
public:
ArrayOfTen() {
m_data = new Object[10];
}
~ArrayOfTen() {
delete[] m_data;
}
Object &operator[](int index) {
/* TODO Range checking */
return m_data[index];
}
private:
Object *m_data;
ArrayOfTen &operator=(const ArrayOfTen &) { }
};
ArrayOfTen myArray;
myArray[0] = Object("hello world"); // bleh
Basically, the ArrayOfTen class keeps an internal array of ten Object elements on the heap. When new[] is called in the constructor, space for ten Objects is allocated on the heap, and ten Objects are constructed. Simiarly, when delete[] is called in the destructor, the ten Objects are deconstructed and then the memory previously allocated is freed.
For most (all?) STL types, resizing is done behind the scenes to make sure there's enough memory set asside to fit your elements. The above class only supports arrays of ten Objects. It's basically a very limiting typedef of Object[10].
To delete the elements pointed at, I wrote a simple functor:
template<typename T>
struct Delete {
void operator()( T* p ) const { delete p; }
};
std::vector< MyType > v;
// ....
std::for_each( v.begin(), v.end(), Delete<MyType>() );
But you should fallback on shared pointers when the vector's contents are to be ... ehm... shared. Yes.
A functor that deletes pointers from STL sequence containers
The standard STL containers place a copy of the original object into the container, using the copy constructor. When the container is destroyed the destructor of each object in the container is also called to safely destroy the object.
Pointers are handled the same way.
The thing is pointers are POD data. The copy constructor for a pointer is just to copy the address and POD data has no destructor. If you want the container to manage a pointer you need to:
Use a container of smart pointers. (eg shared pointer).
Use a boost ptr container.
I prefer the pointer container:
The pointer containers are the same as the STL containers except you put pointers into them, but the container then takes ownership of the object the pointer points at and will thus deallocate the object (usually by calling delete) when the container is destroyed.
When you access members of a ptr container they are returned via reference so they behave just like a standard container for use in the standard algorithms.
int main()
{
boost::ptr_vector<int> data;
data.push_back(new int(5));
data.push_back(new int(6));
std::cout << data[0] << "\n"; // Prints 5.
std::cout << data[1] << "\n"; // Prints 6.
} // data deallocated.
// This will also de-allocate all pointers that it contains.
// by calling delete on the pointers. Therefore this will not leak.
One should also point out that smart pointers in a container is a valid alternative, unfortunately std::auto_ptr<> is not a valid choice of smart pointer for this situation.
This is because the STL containers assume that the objects they contain are copyable, unfortunately std::auto_ptr<> is not copyable in the traditional sense as it destroys the original value on copy and thus the source of the copy can not be const.
STL containers are like any other objects, if you instantiate one it is created on the stack:
std::vector<int> vec(10);
Just like any other stack variable, it only lives in the scope of the function it is defined in, and doesn't need to be manually deleted. The destructor of STL containers will call the destructor of all elements in the container.
Keeping pointers in a container is a dicey issue. Since pointers don't have destructors, I would say you would never want to put raw pointers into an STL container. Doing this in an exception safe way will be very difficult, you'd have to litter your code with try{}finally{} blocks to ensure that the contained pointers are always deallocated.
So what should you put into containers instead of raw pointers? +1 jmucchiello for bringing up boost::shared_ptr. boost::shared_ptr is safe to use in STL containers (unlike std::auto_ptr). It uses a simple reference counting mechanism, and is safe to use for data structures that don't contain cycles.
What would you need for data structures that contain cycles? In that case you probably want to graduate to garbage collection, which essentially means using a different language like Java. But that's another discussion. ;)