If I have class and vector of pointers in class how should I write destructor to properly free memory?
Is it correct?
~Class()
{
for(int i = 0; i<v.size(); i++)
{
delete v[i];
}
}
Or should I also erase elements from vector? Or any other solutions?
~Class()
{
for(int i = 0; i<v.size(); i++)
{
delete v[i];
v.erase(e.begin() + i);
}
}
If I have class and vector of pointers in class how should I write destructor to properly free memory? Is it correct?
It depends.
Do the pointers point to objects that were allocated with new and is this class the owner of those dynamic objects (i.e. is this class responsible for their destruction)? If not, then it's not correct.
Or should I also erase elements from vector?
Your example for erasing elements of the vector is wrong. It will skip half of the elements and thus will not call delete all pointers. After first iteration, first element will have been erased, so the next element has been shifted to the index 0, but next loop deletes and erases the element in index 1.
There's no point in erasing elements of the vector, because it is immediately about to be destroyed.
Or any other solutions?
If you intend for the class to own dynamically allocated objects, prefer using a vector of objects instead of pointers. If you need a vector of pointers for example to allow run time polymorphism, then use a vector of std::unique_ptr. That way you don't need to implement a destructor as the automatically generated would be just fine.
If your class is to supposed to own the objects pointed to, then its sufficient to do:
for (auto p : v) delete p;
If the vector itself is the member of the class then its elements are getting deleted when the class instance object is destroyed, you dont need to do this manually.
And in your example you are also doing it wrong. If its a std::vector you could just call vector's clear() method. Otherwise you would call delete[] p; where p is the pointer to the vector elements itself.
Related
If I use this line
std:vector<MyObject>* vec = new std::vector<MyObject>(100);
If I create MyObject's in the stack and add them to the vector, they remain in the stack, right ?
MyObject obj1;
vec->push_back(obj1);
So if it go to the stack, than MyObject's added to the vector will be gone after method ends ? What will I have inside the vector than? Garbage?
Should I use this instead ?:
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
And if so, what about objects and primitives inside each MyObject ?
Should they also be dynamically created ?
Thank You
The std:vector as any other Standard Library container copies elements into itself, so it owns them. Thus, if you have a dynamically allocated std::vector the elements that you .push_back() will be copied into the memory managed by the std::vector, thus they will be copied onto the heap.
As a side note, in some cases std::vector may move elements if it is safe to do so, but the effect is the same - in the end, all the elements are under std::vector's jurisdiction.
A std::vector<MyObject> looks something like this (in reality it's much more complex):
struct Vector {
MyObject* data;
int size;
}
As you can see, the data is not directly inside the vector object. The vector always allocates the memory for the data on the heap. Here's what happens when:
you call .push_back: The vector copies the object into its own data block (which is on the heap and owned by the vector)
you copy the vector: The copied vector allocates new memory and copies all data from the existing vector into it
As you can see, the vector owns his data. That means, if you push_back a object into it, it doesn't matter where it came from because it gets copied.
If you have a std::vector<MyObject>* you have a pointer to a vector. This vector also owns his data, but you only have a pointer to it. That means, you have to delete it exactly once, otherwise you'll get a memory leak or a crash. Passing around pointers to a vector is OK, but need one class or function that "owns" it. This class/function has to guarantee that the vector still exists when the pointer to it is used.
The third case is a std::vector<MyObject*>. As every vector, this one also owns his data. But this time, the data is only a pointer. So the vector only owns the pointer, but not the objects to which the pointers are pointing. If you do something like this:
std::vector<MyObject*> getObjects() {
MyObject obj1("foo");
MyObject obj2("bar");
std::vector<MyObject*> vec;
vec.push_back(&obj1);
vec.push_back(&obj2);
return vec;
}
The returned vector only contains garbage because you only saved the address to a object on the stack to it. These objects are destroyed when the function returns, but the pointers in the vector are still pointing to that memory block on the stack.
Additionally, keep in mind that this
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
Doesn't store heap allocated objects to the vector. It just stores pointers of type MyObject. If you want to do something like that remember to create the objects first, before you use them. You can do that with something like the following:
for (int i = 0; i < vec->size(); i++) {
vec->at(i) = new MyObject();
}
C++ Memory Leak using list class and push_back
void EMAdd(int n)
{
list<Employee*> em;
for (int i = 1; i <= n; i++)
em.push_back(new Employee());
}
Q1. at the end , the destructor of class list automatically deletes the nodes of em?
Q2. But why this function still has a memory leak?
Thanks,
I would appreciate your answer!
The destructor of Employee is not called. You have a list of pointers to Employee objects, not a list of Employee objects. When the list's destructor is called it will destroy the pointers to the Employee object, but not the objects they point to which you created with new Employee(). They will still be in memory but the only references to them are lost when the list is destroyed, leaking that memory.
Remember every call to new must have a matching call to delete somewhere. However, better yet don't use pointers at all and simply use a list of Employee objects directly.
void EMAdd(int n)
{
list<Employee> em;
for (int i = 1; i <= n; i++)
em.push_back(Employee());
}
Since each element in std::list is already dynamically allocated, a list of pointers is redundant and essentially gives you a set of pointers to pointers.
You should have a list of unique_ptrs so that the memory will be freed upon destruction:
std::list<std::unique_ptr<Employee>> em;
But as David Brown said, you shouldn't be using pointers to begin with.
Once you add an object to a vector in C++, and delete the pointer to that object, will the object inside the vector get deleted too?
for example,
int i = 0;
std::vector<A> aVect;
while(i++ < 10)
{
A *ptrToA = new A();
aVect.push_back(*ptrToA);
delete ptrToA;
}
would it still be valid to call:
aVect.at(2);
Will the call to "delete" destroy the object that was added to the vector, or will it only deallocate the object of the pointer?
Yes you can delete the pointer because, as others have noted you dereference the pointer to it is copied into the vector by value.
It would be more efficient to just construct into the vector like this and avoid new/delete entirely:
int i = 0;
while(i++ < 10)
{
std::vector<A> aVect;
aVect.push_back(A());
}
In C++11 a copy will not be made - the rvalue version of push_back will be used - A will be constructed into it's slot in the vector.
You may not want to create a new vector each time???
std::vector<A> aVect;
int i = 0;
while(i++ < 10)
{
aVect.push_back(A());
}
It will still be valid to call aVect.at(2), since the vector is holding a copy of *ptrToA. When you called aVect.push_back(*ptrToA), it set its A using the assignment operator.
Here you push a copy of the object to the vector and this copy will not get deleted.
However if you write:
int i = 0;
while(i++ < 10)
{
A *ptrToA = new A();
std::vector<*A> aVect;
aVect.push_back(ptrToA);
delete ptrToA;
}
Then you are pushing pointers in the vector and when you delete ptrToA you also delete the element pointed to by the pointer in the vector.
You have created vector of objects of type A: std::vector<A>, which means that when you insert some new object into it, copy of this new object is created and stored into vector.
So yes, it it perfectly safe and valid to access this element even after the new object has been deleted. Deleting the original object won't affect the copy stored in your vector in any way.
Advantage of this kind of vector (vector that holds objects with automatic storage duration) is that memory where these objects are stored is cleaned up automatically once the vector is destructed. So it is less likely that there will be some memory leak in your code as well as less work for you since you don't need to take care of that ugly memory management on your own :)
No it won't. Your std::vector<A> stores instances of objects not pointers. In fact you are dereferencing the pointer while pushing A into the vector.
This will cause a copy of the object (built through copy constructor) to be stored inside your vector. After pushing the object you have 2 instances of an A class. One instance is allocated in the heap (through the new operator). The other instance is on the stack, where aVect is allocated.
On the other hand, if your vector would store pointers (std::vector<*A>), after deleting ptrToA, the pointer stored inside the vector points to an already released memory location (dangling pointer). Trying to access that pointer would cause an error, probably a segfault.
I have two vectors of pointers: arr that contains some elements already and temp, the new vector I want to copy specific elements from arr to. For example I'd like to copy second element of arr to be copied into temp and deleted from arr. How can it be done?
I tried this, but it's not good:
void deleteobject(vector < figure3d *> &arr,int index,vector < figure3d *> &temp)
{
vector < figure3d * > :: iterator i=arr.begin();
temp.insert(temp.begin(),*i);
delete *i;
arr.erase(i);
temp[0]->print();
}
You shouldn't delete the object you're copying since you want to keep it in temp - just erase it from arr.
arr.begin() gives you an iterator pointing to the first element, so if you want the second element, you should advance i one:
++i;
If you want the indexth element, you should advance i by index:
i += index;
Storing raw pointers in a vector, and having to remember to delete them when removing them from the vector is a memory leak waiting to happen. And ass molbdnilo mentioned in another answer, you actually have a memory handling error since you're deleting the object that temp has a pointer to.
From what I understand you want to copy an element at specified index (argument index) and remove it from vector temp. This function could look simple like this:
void deleteobject(std::vector<figure3d*> &arr, int index, std::vector<figure3d*> &temp)
{
temp.insert(temp.begin(), arr[index]);
arr.erase(arr.begin() + index);
}
In this case, you don't copy the object itself, but only a reference to it - thus you don't need to free the memory where this object is stored.
Also note that in your function you call delete *i; which frees the memory where the object pointed by i is stored - and the pointer that stored in arr becomes invalid (dangling pointer), because it points to memory that was freed already.
And I also suggest you to use vector of objects rather than vector of pointers to objects - although elements get copied, it's usually fast enough and there is no troublesome memory management connected with it. And in case there is a good reason why you use vector of pointers ( When to use pointers in C++ ),
I suggest you to use vector of smart pointers instead: if you have TR1 or C++11 support, use std::shared_ptr, otherwise use boost::shared_ptr ( Where is shared_ptr? )
This looks like a job for !
something like this is what I would do:
Class removePredicate{
Public:
bool operator() (figure3d** item) {
//remove logic goes here
}
};
remove_copy_if(arr.begin(), arr.end(), back_inserter(tmp), not1(removePredicate));
This will copy all the elements that you want to remove into tmp. The to actually remove them from arr it's just a simple application of the remove-erase idiom:
erase(remove_if(arr.begin(), arr.end(), not1(removePredicate)), arr.end());
There's probably a way to combine these two steps into one line but you run the risk of losing readability at point.
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 .