Why do I need to delete dynamically created items in vector, manually? Why wouldn't they get deleted or its destructor called when vector got deleted?
Normally something like this, but why needed ?
vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it)
{
delete *it;
}
Firstly, you store raw pointers in your vector. These pointers are just pointers. They can point anywhere. They can point to local objects, which cannot be deleted by delete. And even if they point to dynamically created objects, it doesn't necessarily mean that the user wants them to die with the vector. How is the vector supposed to know all this?
It is a matter of object ownership. Whoever owns the object is responsible for its proper and timely deletion. Ordinary raw pointers do not express ownership. That is why vector can't make any assumptions about whether the objects need to be deleted or not. If you want to tell the vector that it owns its dynamic objects, use corresponding smart pointers.
Secondly, note that your deletion technique is not necessarily safe in the general case. Some standard containers assume that the data you store in them is always valid. When you do delete on each vector element, the data in the vector becomes "invalidated" (pointers become indeterminate). This is OK with a vector. But doing something like this in a "smarter" container, like std::map or std::unordered_set for example, can and will lead to problems. Even if you destroy the container itself immediately afterwards, it is perfectly possible that the container's destruction algorithm might need to analyze (compare, hash etc.) the values of individual elements. And you just killed them all with your cycle.
Smart pointers naturally resolve this matter. But if you have to use a manual delete for raw pointers stored in a standard container, a better sequence of steps would be this
Retrieve the value of the element at i and store it in pointer p
Erase the element at i from the container
Do delete p
In the end you end up with an empty container and deleted 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.
Because the language has no way of knowing whether you need them to remain alive when you're done. What if you inserted some pointers to stack objects or something like that? Boom.
This, however, can be remedied by using a smart pointer, which will implement an appropriate policy as to automatic destruction. unique_ptr and shared_ptr are the most common and useful.
The destructor is not called because the pointer does not own the object to which it points.
In C++11, a std::unique_ptr<T> does indeed own the object to which it points. In this case, the destructor is called when the pointer is released, which is probably the behavior you want. (If you don't have a C++11 compiler but have a reasonably recent pre-C++11 compiler, unique_ptr is still available as part of TR1.)
The implementation of vector was just made to delete its memory only. Pointers do not have deconstructors. And in C++, there is no garbage collection or logic to see that it is pointers and recursive delete it.
If you would like to attend the next ISO meeting and propose that, be my guest, but for me, I just put it in an 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;
}
}
Related
When using list what are the good habits to manage memory,
dynamic allocation and release (free) wheneve we dont need it anymore. To keep program light and avoid memory leaks ensure a good memory managment (i now it's a wide question)
how to initialize a list of pointers to objects initially with N items ? should i use the operator new to allocate memory?
if i want to delete completely (free) an item from a list and program memory space, should i use pop or remove or erase ? differences?
should i use operator delete while iterating a list or .erase .remove is enough to free space ?
.
class myclass { /* whatever attributes, methodes */ };
list<myclass *> lst (5); //5 pointers will be NULL this way
for (list<myclass *>::iterator it=lst.begin(); it != lst.end(); it++) {
myclass *obj= *it;
delete obj; //error
it = lst.erase(it);
}
C++ has value semantics. A list owns the objects on it. This is true whether it's a list of int (built-in type), std::string (library type) or myclass (yours). Make sure that your class can be copied (or at least moved, but that's an advanced topic). Also make sure that your class destructor works properly, because list::clear will call it.
Do not try to use lists of pointers, initially. When you do, use lists of smart pointers, but that is already an advanced topic. Lists of "dumb" pointers should be avoided outright.
Though I think you should listen to what everyone else said, I figured I would still answer your questions so you know the answer should you need to know them. Smart pointers are definitely best to use nowadays, but when I learned pointers in C++, I initially used new/delete and I feel it helps you understand better than just going straight to smart pointers (I know you said you don't know what they are, so they just manage the memory for you).
how to initialize a list of pointers to objects initially with N items ? should i use the operator new to allocate memory?
As you did, list<myclass *> lst (5) would be just fine to make your list of pointers, and yes, you should use new for each of the elements in the list in order to allocate memory there. For example,
list<myclass*>::iterator it = lst.begin();
*it = new myclass();
if i want to delete completely (free) an item from a list and program memory space, should i use pop or remove or erase ? differences?
To get rid of an element from the list, you can use the list's erase function found here: http://www.cplusplus.com/reference/list/list/erase/
That will remove the element from the list, however be careful here if using pointers, because you'll need to make sure that you free the pointer that the list node was holding before you erase this node (see below)
should i use operator delete while iterating a list or .erase .remove is enough to free space ?
.erase will delete the element from the list, but it will not free the pointer for you, you will would explicitly need to do something like this.
list<myclass*> lst(5);
list<myclass*>::iterator it = lst.begin();
*it = new myclass();
// and when you're ready to delete a node
if(*it != NULL)
delete *it;
lst.erase(it);
Also, in your for loop, be sure to check, as I do, if the pointer is NULL before deleting it. This is likely why you got an error on the delete call. Since it is not allowed to store memory at NULL, it is clearly not allowed to delete the memory there. That will give you a segmentation fault. It's always good to check for NULL before deleting just in case unless you are positive it will be holding data.
Hope this helps. It's not the best way to do it with newer versions of C++ available, but it should answer your question as asked.
how to initialize a list of pointers to objects initially with N items ? should i use the operator new to allocate memory?
Don't. Let the list handle the allocation and deallocation.
lst.push_back(myclass());
If you have a number of items to go into the list, you can take advantage of initializers. The following uses a myclass constructor that takes a string and an int as an example.
list<myclass> lst {{"one", 1},{"two", 2},{"three", 3}};
If this is an assignment which requires pointer use, definitely use new rather than malloc and it's family to allocate storage, but consider this a last resort.
Preferred would be to use a smart pointer. The big two of these are unique_ptr and shared_ptr.
list<unique_ptr<myclass>> lst;
lst.push_back(unique_ptr<myclass>(new myclass()));
or in C++14 or newer,
lst.push_back(make_unique<myclass>());
The unique_ptr automatically destroys the myclass when removed from the list.
But I see no advantage to this over the list directly containing myclass unless myclass is the base class of a class hierarchy. If you are in the early stages of learning C++, do some reading and practice of the basics before going this route.
list<shared_ptr<myclass>> lst;
lst.push_back(shared_ptr<myclass>(new myclass()));
Makes a reference-counted my class that can be shared with others. When every user has disposed of their shared_ptr, the myclass will be destroyed. This is great for systems with callbacks. The callback object will be there when the callback fires, preventing all sorts of fun segfaults. The downside is the lifetime of the object is blurred. When it is destroyed depends on the outstanding shared_ptrs.
Do not allow circular references of shared_ptrs, as the reference count will never drop to zero. There might be some really sneaky code built in to assist here, but I wouldn't count on it. Bad program design anyway.
Raw pointer with new. Just don't do this. You have better, safer options.
lst.push_back(new myclass());
if i want to delete completely (free) an item from a list and program memory space, should i use pop or remove or erase ? differences?
remove doesn't exist for list. Pop, depending on which one you use, either removes the first or last element. Use pop if the list represents a queue or a stack. erase can remove any element, so long as you know where it is. Finding it may require a search.
With a stored object, list<myclass> you might not get any memory back. The list may save the allocated RAM so it doesn't have to ask for it again later. Frankly I'm not sure what the standard's policy is for lists. For vectors, the object is destroyed, but the space remains allocated unless you manually force a resizing. I believe list behaves the same way because of the presence of the resize method and the wording of the documentation.
If you have a raw pointer, you must delete it, then remove it from the list. You can't do it in the other order because once removed from the list the pointer is inaccessible and the RAM is lost to you. Yeah, you can copy the pointer, then remove it from the list, then delete the copy, but why go to the extra effort? I believe the pointer will still be allocated in the list, but will be inaccessible and awaiting reuse.
If you use a unique_ptr, the unique_ptr handles the disposal for you. With a shared_ptr, disposal is also handled for you, but you don't necessarily know when. Another copy of the shared_ptr may exist, blocking destruction.
should i use operator delete while iterating a list or .erase .remove is enough to free space ?
Covered above in my answer to 2. With a pointer, removal from the list only removes the pointer to myclass and leaves you without a pointer to myclass and the RAM is lost. With a smart pointer, the myclass is destroyed by the smart pointer with no further effort required.
But you may not get any noticeable amount of RAM back if it is being held by the list for reuse.
Recently I've met with opinion that I shouldn't use vector of pointers.
I wanted to know - why I cant?
For example if I have a class foo it is possible to do this:
vector <foo*> v;
v.push_back(new foo());
I've already seen some people down voting such practices, why is that?
Storing plain pointers in a container can lead to memory leaks and dangling pointers. Storing a pointer in a container does not define any kind of ownership of the pointer. Thus the container does not know the semantics of desctruction and copy operations. When the elements are being removed from the container the container is not aware how to properly destroy them, when a copy operation is performend no ownership semanctics are known. Of course, you can always handle these things by yourself, but then still a chance of human error is possible.
Using smart pointers leaves the ownership and destruction semantics up to them.
Another thing to mention is that containers are divided into non-intrusive and intrusive contaiers - they store the actual provided object instead of a copy so it actually comes down to a collection of pointers. Non intrusive pointers have some advantages, so you can't generalize that pointers in a container is something that should be avoided in all times, still in most cases it is recommended.
Using an vector of raw pointers is not necessary bad style, as long as you remember that the pointers do not have ownership semantics. When you start using new and delete, it usually means that you're doing something wrong.
In particular, the only cases where you should use new or delete in modern C++ code is when constructing unique_ptr's, or constructing shared_ptr's with custom deleters.
For example, assume that we have an class that implemented an bidirectional Graph, a Graph contains some amount of Vertexes.
class Vertex
{
public:
Vertex();
// raw pointer. No ownership
std::vector<Vertex *> edges;
}
class Graph
{
public:
Graph() {};
void addNode()
{
vertexes.push_back(new Vertex); // in C++14: prefer std::make_unique<>
}
// not shown: our Graph class implements a method to traverse over it's nodes
private:
// unique_ptr. Explicit ownership
std::vector<std::unique_ptr<Vertex>> vertexes;
}
void connect(Vertex *a, Vertex *b)
{
a->edges.push_back(b);
b->edges.push_back(a);
}
Notice how i have an vector of raw Vertex * in that Vertex class? I can do that because the lifetime of the Vertexes that it points to are managed by the class Graph. The ownership of my Vertex class is explicit from just looking at the code.
An different answer suggests using shared_ptr's. I personally dislike that approach because shared pointers, in general, make it very hard to reason about the lifetime of objects. In this particular example, shared pointers would not have worked at all because of the circular references between the Vertexes.
Because the vector's destructor won't call delete on the pointers, so it's easy to accidentally leak memory. A vector's destructor calls the destructors of all the elements in the vector, but raw pointers don't have destructors.
However, you can use a vector of smart pointers to ensure that destroying the vector will free the objects in it. vector<unique_ptr<foo>> can be used in C++11, and in C++98 with TR1 you can use vector<tr1::shared_ptr<foo>> (though shared_ptr has a slight overhead compared to a raw pointer or unique_ptr).
Boost also has a pointer container library, where the special delete-on-destruction behavior is built into the container itself so you don't need smart pointers.
One of the problems is exception-safety.
For example, suppose that somewhere an exception is thrown: in this case, the destructor of std::vector is called. But this destructor call does not delete the raw owning pointers stored in the vector. So, the resources managed by those pointers are leaked (these can be both memory resources, so you have a memory leak, but they could also be non-memory resources, e.g. sockets, OpenGL textures, etc.).
Instead, if you have a vector of smart pointers (e.g. std::vector<std::unique_ptr<Foo>>), then if the vector's destructor is called, each pointed item (safely owned by a smart pointer) in the vector is properly deleted, calling its destructor. So, the resources associated to each item ("smartly" pointed to in the vector) are properly released.
Note that vectors of observing raw pointers are fine (assuming that the lifetime of the observed items exceeeds that of the vector). The problem is with raw owning pointers.
I will talk specifically about a vector of pointers that's responsible for managing the lifetime of the pointed objects, because that's the only case where a vector of pointers is clearly a questionable choice.
There are much better alternatives. Specifically:
std::vector<std::shared_ptr<foo>> v;
and
std::vector<std::unique_ptr<foo>> v;
and
boost::ptr_vector<foo> v; // www.boost.org
The above versions tell the user how the lifetime of the objects is taken care of. Using raw pointers instead can possibly lead to the pointers being deleted either more or less than once, especially if the code is modified over time, or if exceptions become involved.
If you use an interface like ´shared_ptr´ or ´unique_ptr´, this self-documents the lifetime management for the user. When you use raw pointers you have to be clearly document how you handle the lifetime management of the objects, and hope that the right people read the documentation at the right time.
The benefits of using vectors of raw pointers are that you have more flexibility in how taking care of lifetime management, and that you can possibly get rid of some performance and space overhead.
There is absolutely no problem in using a vector of pointers. Most here are suggesting smart pointers, but I just have to say, there is no problem with using a vector of pointers without smart pointers. I do it all the time.
I agree with juanchopanza that the problem is your example is the pointers come from new foo(). In a normal completely-valid use case, you might have the objects in some other collection C, so that the objects will automatically get destroyed when C is destroyed. Then, in doing in the process of doing in-depth operations on the objects in C, you might create any number of other collections containing pointers to the objects in C. (If the other collections used object copies that would be time and memory wasteful, while collections of references is expressly forbidden.) In this use case, we never want to destroy any objects when a collection of pointers is destroyed.
Suppose there's a vector of Items
vector<Item*> items; //{item1, item2, item3}
Then, in other part of the code,
items[1]->suicide();
where the suicide function is:
void Item::suicide()
{
delete this;
}
What is items vector size and how it's arrangement now?
It is okay to do this?
Edit (may I ask an additional question?): If the desired arrangement of the output is {item1, item3}, size is 2, and no dangling pointer, how to do it in a self-destructing way (from the item2 itself)?
Edit 2 : Thanks for all the answers! Awesome. So I finally decided and found the way to do it from outside of the object because it was a bad practice and unnecessarily complicated
What is items vector size and how it's arrangement now? The same. The function call does not change the vector contents nor size at all. It just frees the memory the pointer is pointing to.
Is it okay to do this? More precisely: Is it legal C++? Yes. Is it good style programming? No. Let me elaborate on the latter:
There should be a separation of concerns: Who's responsible for memory management? The container or the user of the class Item or the class Item itself?
Typically the container or user should do that, because he knows what's going on.
What's the way to do that? Memory management in modern and safe C++ code is mostly done using smart pointers like std::shared_ptr and std::unique_ptr and containers like std::vector and std::map.
If the class Item is a value type (that means you can simply copy it and it has no polymorphic behavior in terms of virtual functions), then just use std::vector<Item> instead for your code. Destructors will be called automatically as soon as an element is removed from the container. The container does it for you.
If the class Item has polymorphic behavior and can be used as a base class, then use std::vector<std::unique_ptr<Item>> or std::vector<std::shrared_ptr<Item>> instead and prefer the std::unique_ptr solution, because it adds less overhead. As soon as you stop referring to an object, it will be deleted automatically by the destructor of the smart pointer you are using. You (almost) don't need to worry about memory leaks anymore.
The only way you can produce memory leaks is that you have objects that contain std::shared_ptrs that refer to each other in cyclic way. Using std::unique_ptrs can prevent this kind of trouble. Another way out are std::weak_ptrs.
Bottom line: Don't provide a function suicide(). Instead put the responsibility solely into the hands of the calling code. Use standard library containers and smart pointers to manage your memory.
Edit: Concerning the question in your edit. Just write
items.erase( items.begin() + 1 );
This will work for all types: std::vector of values or pointers. You can find a good documentation of std::vector and the C++ Standard library here.
The suicide member doesn't change the vector. So the vector contains an element which is an invalid pointer and formally you can't do much with an invalid pointer, even copying or comparing it is undefined behavior. So anything which access it, included vector resizing, is an UB.
While any access if formally UB, there is a good chance that your implementation doesn't behave strangely as long as you don't dereference the pointer -- the rationale for making any access UB is machines where loading an invalid pointer in a register can trap and while x86 is part of them, I don't know of widespread OS working in this mode.
Your suicide function does not to anything with the Items vector, let alone it knows anything about it. So from the vector's point of view: nothing changes when you call the function and it's ok to do that.
The pointer will become invalid, that's all. You should be careful to not to delete it again. vector<Item*> will NOT delete elements on its own.
The vector has no idea what you're doing elsewhere in the code, so it'll keep a dangling pointer to the original Item.
"Is it OK do do that?"
After suiciding the item, you should adjust the vector manually to no longer keep that dangling pointer.
That's ok in case of vector of pointers as vector will not call Item's destructor. But you have to somehow know which pointers are still valid.
If you are storing Items in vector by value, calling Item's destructor is not ok. When vector will be destroyed or cleared, it will call item's destructor again, causing application crash.
Wow, It seems that you make a typing error. It should be vector<Item *> Items;
As to your question:
the size of vector Items does not change, means that, it still has three pointers to Item objects.
the content of the vector does not change:
before Items[1]->suicide() , Items[0] = 0x000001, Items[1] = 0x000005, Items[2] = 0x000009
after Items[1]->suicide(), Items[0] = 0x000001, Items[1] = 0x000005, Items[2] = 0x000009
It's definitely OKAY to do so.
Besides, the vector will manage its memory automatically, when you push some elems into it while the capacity is not enough, it will reallocate a larger space, BUT, when you pop some elems or erase some elems, it will never give the redundant memory to the system.
The code of Items[1]->sucide() just return the memory held or pointed by the pointer Items[1] to the system, it will do nothing on the pointer itself, Items[1] still holds the same value, but point an unsafe area.
Unexpectedly, you have made a Design Pattern, suppose you want to design a class and you ONLY allow allocate any object of it on the Heap, you may write the following code:
class MustOnHeap
{
private:
~MustOnHeap() { // ...}
public:
void suicide() { delete this;}
};
Then ,the class can not have any instance that is alloacated on the stack, because the destructor is private, and the compiler must arrange the calling of destructor when the object walk out its scope.
Therefor, you must allocate them on the heap, MustOnHeap* p = new MustOnHeap; and then destroy it explicitly : p->suicide();
I just wonder what's wrong with vector of pointer. some of my friend recommend me to use list instead of vector. will this cause a problem:
vector<Fruit*> basket;
basket.push_back(new Apple());
basket.push_back(new Orange());
vector<Fruit*> temp;
temp.push_back(basket[1]);
If I delete vector temp, do I destroy the basket[1] object too? if not, what's the problem with using vector of pointer?
If I delete vector temp, do I destroy the basket[1] object too?
No. First of all, you cannot delete temp; rather, it will get destroyed when going out of scope. And when this happens, the objects pointed by elements of the vector won't be automatically deleted.
This is, however, not a specific problem of vector: using list will not save you from this issue. The problem is rather with raw pointers. If you want the pointed objects to be automatically deallocated when the the lifetime of the last pointer which points to it ends, you should use smart pointers.
Depending on the ownership policy that your application needs, you might choose between shared_ptr and unique_ptr. The caveat with shared_ptr is that referencing cycles shall be avoided, to prevent mutually referencing objects from keeping each other alive. You may want to check weak_ptr in this respect.
Finally, unless you have a good reason for not using vector, vector should be the default choice for a container. From Paragraph 23.2.3/2 of the C++11 Standard:
The sequence containers offer the programmer different complexity trade-offs and should be used accordingly. vector or array is the type of sequence container that should be used by default. list or forward_list should be used when there are frequent insertions and deletions from the middle of the sequence. deque is the data structure of choice when most insertions and deletions take place at the beginning or at the end of the sequence.
If either of the vectors, basket or temp, are destroyed none of the Fruits are destroyed. Anything that is dynamically allocated with new must be deleted. When the vectors go out of scope, they do not delete the objects that are pointed to by their elements. If you delete an object through one vector that is pointed to in the other vector, both point at the now deleted object.
Since your vectors have automatic storage duration, you definitely must not do delete basket; or delete temp;.
It's not recommended to use raw pointers in general, especially with dynamically allocated storage that you may forget to delete. In this case, however, you do need polymorphic behaviour, which is provided by pointers. You should use a smart pointer to avoid the problems with raw pointers. Try a std::vector<std::shared_ptr<Fruit>>.
I'm having some trouble using the std container classes (list, map etc.) in C++. The problem seems to be to do with removing items for the containers. I'm trying to store pointers to objects within a container, and then when I want to remove the item from the container I use either erase or remove. When I do this, does the container actually delete the object that was in the container, or simply remove the pointer from the container?
What I'm hoping is that it just removes the pointer, because I'm using the containers to group objects and and object may be in more than one group, so I don't want it to be deleted when it's removed from a container!
Thanks!
When I do this, does the container actually delete the object that was in the container, or simply remove the pointer from the container?
The latter.
... so I don't want it to be deleted when it's removed from a container!
This is in fact what happens, but I'd still like to point out std::shared_ptr, which can make pointer/container interactions a lot easier.
When I do this, does the container actually delete the object that was in the container, or simply remove the pointer from the container?
Standard Library containers do not take the responsibility of deallocating dynamic memory of pointer elements. You will have to take care of deallocating the dynamic memory yourself, If you are storing a raw pointer in the container.
This is where power of the RAII concept in C++ comes to your rescue. You can use a Smart pointer instead of raw pointers inside the container and once you do that the deallocation will be implicitly handled by the smart pointer instead of you having the overhead of explicitly handling the memory management.
There are a number of smart pointers available and I purposefully restrained myself from suggesting a particular smart pointer because it will specifically depend on the ownership and the lifetime of the object involved.Check the link and choose a appropriate smart pointer as per your requirement.
Effective STL by Scott Meyer will give you the answer about storing raw pointer in container classes.
If you don't want to use smart_pointers or other similar things, but storing raw pointer, you have to explicitly delete it if you want to clear the memory associated.
When allocating, for example a std::vector then before clearing it, you have to delete each element of it manually.
std::vector<int*> v(10;
for (int i=0; i<10; i++)
v.at(i) = new int;
wrong way
v.clear(); // !!! MEMORY LEAK
the correct way is
for (int i=0; i<10; i++)
delete v.at(i);
and then
v.clear();
comipler doesn't remove object which placed in heap-memory