Reputation: 2486
Consider this code:
#include <vector>
void Example()
{
std::vector<TCHAR*> list;
TCHAR* pLine = new TCHAR[20];
list.push_back(pLine);
list.clear(); // is delete called here?
// is delete pLine; necessary?
}
Does list.clear()
call delete
on each element? I.e. do I have to free the memory before / after list.clear()
?
Upvotes: 69
Views: 97046
Reputation: 16994
std::vector
does call the destructor of every element it contains when clear()
is called.
In your particular case, it destroys the pointer but the objects remain.
Smart pointers are the right way to go, but be careful. auto_ptr
cannot be used in std containers. boost::scoped_ptr
can't either. boost::shared_ptr
can, but it won't work in your case because you don't have a pointer to an object, you are actually using an array. So the solution to your problem is to use boost::shared_array
.
But I suggest you use std::basic_string<TCHAR>
instead, where you won't have to deal with memory management, while still getting the benefits of working with a string.
Upvotes: 56
Reputation: 13477
You could just write a simple template function that does this for you:
template <class T>
void deleteInVector(vector<T*>* deleteme) {
while(!deleteme->empty()) {
delete deleteme->back();
deleteme->pop_back();
}
delete deleteme;
}
Maybe something in here is bad practice but I don't think so. It looks okay to me though comments are always nice.
Upvotes: 8
Reputation: 61795
No (you need to do the delete yourself at the end as you suggest in your example as the destruction of the bald pointer doesnt do anything). But you can use a boost [or other RAII-based idiom] smart pointer to make it Do The Right Thing (auto_ptr
would not work correctly in a container as it has incompatible behaviour under copying etc.), but be sure you understand the pitfalls of such smart pointers before use. (As Benoit mentions, in this case, basic_string
is what you're really looking for here.)
Having said that there's a need to understand the pitfalls of smart pointers, having them take care of the memory management implicitly so you dont have to do it explicitly is far less error-prone.
EDIT: Substantially revised to encompass the elements Benoit brought into his far more thorough answer, thanks to strong prodding from the Earwicker and James Matta - thanks for pushing me to do the due diligence on this!
Upvotes: 42
Reputation: 39858
You might also be able to use the Boost Pointer Container Library. Not specifically recommended here (again because you're using arrays instead of single objects, though std::string
would take care of that), but it's a useful and little-known library that solves the problem stated in the title.
Upvotes: 0
Reputation: 6849
Here's one way that you can tell that it doesn't - try it on a class that's not fully defined:
#include <vector>
class NotDefined;
void clearVector( std::vector<NotDefined*>& clearme )
{
clearme.clear(); // is delete called here?
}
If this snippet compiles, then it can't be calling the destructor, because the destructor isn't defined.
Upvotes: 9
Reputation: 421988
Nope. It doesn't do that since there is no guarantee you are not using the pointer anywhere else. If it wasn't a pointer variable, it would free them (by calling the destructor)
Upvotes: 8