How to use STL map? - c++

I have a private field
std::map<std::string, std::multiset<GraphObject*>>* the_Map;
How can I allocate memory for it and insert a GraphObject?
Do I have to use the new operator?
the_Map = new map<string,multiset<GraphObject*>>;
And how can I insert a new GraphObject?
It's part of a datastructure and I really need a pointer to a map.

How can I allocate memory for it and insert a GraphObject?
It doesn't want to be a pointer at all; just make the map itself a member of the class and memory allocation will happen automatically.
Correctly inserting an object is rather fiddly, since you're storing pointers there too. If it doesn't need to be a pointer, then storing objects would make your life much easier. If it really does have to be a pointer (e.g. because GraphObject is a polymorphic base class), I would recommend storing smart pointers: std::unique_ptr, or std::tr1::shared_ptr or boost::shared_ptr if you're stuck in the past.
If you really, really need to use raw pointers for some insane reason, then the closest you can get to an exception-safe insertion is probably:
GraphObject * object = new Whatever(...);
try {
the_Map[key].insert(object);
} catch(...) {
delete object;
throw;
}
or if you don't care about the possiblity of memory leaks on insertion failure:
the_Map[key].insert(new Whatever(...));
Also don't forget to delete each object when you remove it; that won't happen automatically.
I really need a pointer to a map.
No you don't. But if you really believe you do, and want to ignore everyone's advice not to, then you'll need an actual map to point to. I would recommend that you make this map a member of the class, so that its lifetime is managed automatically.
If you really want to make life difficult for whoever maintains the code, then I suppose you could allocate one with new. In that case, remember to delete it when you've finished with it; probably in the class destructor. And if you do that, remember the Rule of Three and implement or delete the copy constructor and copy-assignment operator, since the default implementations will do the wrong thing.

Why you're storing a ::std:multiset of GraphObject *'s is a bit obscure, but lets roll with that.
This is an answer that is really trivially answered by documentation, but there is no question too dumb for StackOverflow, so...
the_Map = new map<string,multiset<GraphObject*>>;
That is indeed how you allocate memory for your map. It's generally not a good idea to have bare pointers to things lying around, but you insisted, and that's how you do it. That means you will have to remember to delete it at some point as well. And you will have to make sure that the copy construct of the class that holds the pointer does the right thing (and said right thing will be fairly complicated).
You have an interesting problem now. You are storing a multiset in each map entry. Fortunately this multiset will automatically be created and initialized to empty when a previously unknown key is accessed. OTOH, your use of bare pointers means that you have an exception safety problem. It's possible to leak memory if an exception is thrown anywhere along the way. So you have to catch any exceptions and clean up your object:
GraphObject *tmp = new GraphObject;
try {
(*the_Map)[key].insert(tmp);
} catch (...) {
delete tmp;
throw;
}
The fact your question is so basic makes me question your assertions about needing to use pointers. And I really wonder if you wouldn't rather have a multimap rather than a map from string -> multiset. But, you're adamant about the general form of your data structure. So the above is how you'd use it.
I'll also say that this data structure's copious use of bare pointers is a pretty bad idea. You'll have to write a pretty sophisticated functions to properly deconstruct or copy the whole mess.
Edit: sigh Coding at 4am on a data structure I would never create myself led me to write some very stupid code. The current version is much better. Though this answer is really much better than mine.

Related

list of pointers initialize and release memory

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.

Deleting dynamically allocated memory from a map

I've got a map of dynamically allocated object and was wondering what the best way of deleting them was?
I was thinking maybe an interator? Something like:
studentlist::const_iterator deletemem = studentmap.begin();
for(studentlist::const_iterator deletemem=studentmap.begin(); deletemem!=studentmap.end();++deletemem)
{
Record *z=deletemem->second // Record is the type of object stored in the map student map
delete z;
}
But i'm not sure, any help would be much appreciated!
Your code looks fine. However, manually deleting is probably not exception-safe. You might consider using share_ptr (either the one from Boost, or, if you use C++0x, the standard implementation) for the values or using a boost::ptr_map.
Edit: To delete the actual data in the map, call studentmap.clear() after deleting all the contents. This will remove all elements from the map.
Edit 2: The problem with your solution arises when, for instance due to an exception, your cleanup code does not get called. In that case you leak memory. To overcome this problem, you can employ the RAII-idiom. Two possible ways of doing this are described above.
A better solution would be to encapsulate your dynamically allocated memory inside another object which is stack allocated. This could either be one of your own invention or you could use the shared_ptr class from the new C++ standard or from boost.
Your code should work, but you should clear the studentmap at the end.
Of course, you have also to invalidate any other object that should hold a copy of the pointers you are deallocating, otherwise your application will probably crash.

Why is creating STL containers dynamically considered bad practice?

Title says it.
Sample of bad practive:
std::vector<Point>* FindPoints()
{
std::vector<Point>* result = new std::vector<Point>();
//...
return result;
}
What's wrong with it if I delete that vector later?
I mostly program in C#, so this problem is not very clear for me in C++ context.
As a rule of thumb, you don't do this because the less you allocate on the heap, the less you risk leaking memory. :)
std::vector is useful also because it automatically manages the memory used for the vector in RAII fashion; by allocating it on the heap now you require an explicit deallocation (with delete result) to avoid leaking its memory. The thing is made complicated because of exceptions, that can alter your return path and skip any delete you put on the way. (In C# you don't have such problems because inaccessible memory is just recalled periodically by the garbage collector)
If you want to return an STL container you have several choices:
just return it by value; in theory you should incur in a copy-penality because of the temporaries that are created in the process of returning result, but newer compilers should be able to elide the copy using NRVO1. There may also be std::vector implementations that implement copy-on-write optimization like many std::string implementations do, but I've never heard about that.
On C++0x compilers, instead, the move semantics should trigger, avoiding any copy.
Store the pointer of result in an ownership-transferring smart pointer like std::auto_ptr (or std::unique_ptr in C++0x), and also change the return type of your function to std::auto_ptr<std::vector<Point > >; in that way, your pointer is always encapsulated in a stack-object, that is automatically destroyed when the function exits (in any way), and destroys the vector if its still owned by it. Also, it's completely clear who owns the returned object.
Make the result vector a parameter passed by reference by the caller, and fill that one instead of returning a new vector.
Hardcore STL option: you would instead provide your data as iterators; the client code would then use std::copy+std::back_inserter or whatever to store such data in whichever container it wants. Not seen much (it can be tricky to code right) but it's worth mentioning.
As #Steve Jessop pointed out in the comments, NRVO works completely only if the return value is used directly to initialize a variable in the calling method; otherwise, it would still be able to elide the construction of the temporary return value, but the assignment operator for the variable to which the return value is assigned could still be called (see #Steve Jessop's comments for details).
Creating anything dynamically is bad practice unless it's really necessary. There's rarely a good reason to create a container dynamically, so it's usually not a good idea.
Edit: Usually, instead of worrying about things like how fast or slow returning a container is, most of the code should deal only with an iterator (or two) into the container.
Creating objects dynamically in general is considered a bad practice in C++. What if an exception is thrown from your "//..." code? You'll never be able to delete the object. It is easier and safer to simply do:
std::vector<Point> FindPoints()
{
std::vector<Point> result;
//...
return result;
}
Shorter, safer, more straghtforward... As for the performance, modern compilers will optimize away the copy on return and if they are not able to, move constructors will get executed so this is still a cheap operation.
Perhaps you're referring to this recent question: C++: vector<string> *args = new vector<string>(); causes SIGABRT
One liner: It's bad practice because it's a pattern that's prone to memory leaks.
You're forcing the caller to accept dynamic allocation and take charge of its lifetime. It's ambiguous from the declaration whether the pointer returned is a static buffer, a buffer owned by some other API (or object), or a buffer that's now owned by the caller. You should avoid this pattern in any language (including plain C) unless it's clear from the function name what's going on (e.g strdup, malloc).
The usual way is to instead do this:
void FindPoints(std::vector<Point>* ret) {
std::vector<Point> result;
//...
ret->swap(result);
}
void caller() {
//...
std::vector<Point> foo;
FindPoints(&foo);
// foo deletes itself
}
All objects are on the stack, and all the deletion is taken care of by the compiler. Or just return by value, if you're running a C++0x compiler+STL, or don't mind the copy.
I like Jerry Coffin's answer. Additionally, if you want to avoid returning a copy, consider passing the result container as a reference, and the swap() method may be needed sometimes.
void FindPoints(std::vector<Point> &points)
{
std::vector<Point> result;
//...
result.swap(points);
}
Programming is the art of finding good compromises. Dynamically allocated memory can have some place of course, and I can even think to problems where a good compromise between code complexity and efficiency is obtained using std::vector<std::vector<T>*>.
However std::vector does a great job of hiding most needs of dynamically allocated arrays, and managed pointers are many times just a perfect solution for dynamically allocated single instances. This means that it's just not so common finding cases where an unmanaged dynamically allocated container (or dynamically allocated whatever, actually) is the best compromise in C++.
This in my opinion doesn't make dynamic allocation "bad", but just "suspect" if you see it in code, because there's an high probability that better solutions could be possile.
In your case for example I see no reason for using dynamic allocation; just making the function returning an std::vector would be efficient and safe. With any decent compiler Return Value Optimization will be used when assigning to a newly declared vector, and if you need to assign the result to an existing vector you can still do something like:
FindPoints().swap(myvector);
that will not do any copying of the data but just some pointer twiddling (note that you cannot use the apparently more natural myvector.swap(FindPoints()) because of a C++ rule that is sometimes annoying that forbids passing temporaries as non-const references).
In my experience the biggest source of needs of dynamically allocated objects are complex data structures where the same instance can be reached using multiple access paths (e.g. instances are at the same time both in a doubly linked list and indexed by a map). In the standard library containers are always the only owner of the contained objects (C++ is a copy semantic language) so it may be difficult to implement those solutions efficiently without the pointer and dynamic allocation concept.
Often you can stil reasonable-enough compromises that just use standard containers however (may be paying some extra O(log N) lookups that you could have avoided) and that, considering the much simpler code, can be IMO the best compromise in most cases.

How do ensure that while writing C++ code itself it will not cause any memory leaks?

Running valgrind or purify would be the next steps
But while while writing the code itself how do you ensure that it will not cause any memory leaks?
You can ensure following things:-
1: Number of new equal to delete
2: Opened File descriptor is closed or not
Is there any thing else?
Use the RAII idiom everywhere you can
Use smart pointers, e.g. std::auto_ptr where appropriate. (don't use auto_prt in any of the standard collections as it won't work as you think it will)
Avoid creating objects dynamically wherever possible. Programmers coming from Java and other similar languages often write stuff like:
string * s = new string( "hello world" );
when they should have written:
string s = "hello world";
Similarly, they create collections of pointers when they should create collections of values. For example, if you have a class like this:
class Person {
public:
Person( const string & name ) : mName( name ) {}
...
private:
string mName;
};
Rather than writing code like:
vector <Person *> vp;
or even:
vector <shared_ptr <Person> > vp;
instead use values:
vector <Person> vp;
You can easily add to such a vector:
vp.push_back( Person( "neil butterworth" ) );
and all the memory for both Person and the vector is managed for you. Of course, if you need a collection of polymorphic types, you should use (smart) pointers
Use Smart Pointers
Use RAII
Hide default copy ctors, operator=()
in EVERY CLASS,
unless a) your class is trivial and
only uses native types and YOU KNOW
IT ALWAYS WILL BE SO b) you
explicitly define your own
On 1) RAII, the idea is to have deletes happen automatically, if you find yourself thinking "I just called new, I'll need to remember to call delete somewhere" then you're doing something wrong. The delete should either be a) automatic or b) be put in a dtor (and which dtor should be obvious).
On 2) Hiding defaults. Identifying rogue default copy ctors etc can be a nightmare, the easiest thing is to avoid them by hiding them. If you have a generic "root" object that everything inherits from (can be handy for debugging / profiling anyway) hide the defaults here, then when an something tries to assign / copy an inheriting class the compiler barfs because the ctor's etc aren't available on the base class.
Minimize the calls to new by using the STL containers for storing your data.
I'm with Glen and jalf regarding RAII at every opportunity.
IMHO you should aim to write completely delete-free code. The only explicit "delete"s should be in your smart pointer class implementations. If you find yourself wanting to write a "delete", go and find an appropriate smart pointer type instead. If none of the "industry standard" ones (boost's etc) fit and you find yourself wanting to write some bizzare new one, chances are your architecture is broken or at the least there will be maintenance difficulties in future.
I've long held that explicit "delete" is to memory management what "goto" is to flow control. More on this in this answer.
I always use std::auto_ptr when I need to create a new object on the heap.
std::auto_ptr<Foo> CreateFoo()
{
return std::auto_ptr<Foo>(new Foo());
}
Even if you call
CreateFoo()
it won't leak
The basic steps are twofold:
Firstly, be aware that every new requires a delete. So, when you use the new operator, up your awareness of what that object will be doing, how it will be used, and how its lifetime will be managed.
Secondly, make sure that you never overwrite a pointer. You can do this using a smart pointer class instead of raw pointers, but if you do make absolutely sure you never use it with implicit conversion. (an example: using MSXML library, I created a CCOMPtr smart pointer to hold nodes, to get a node you call the get_Node method, passing in the address of the smart pointer - which had a conversion operator that returned the underlying pointer type. Unfortunately, this meant that if the smart pointer already held data, that member data would be overwritten, leaking the previous node).
I think those 2 cases are the times when you might leak memory. If you only use the smart pointer directly - never allowing its internal data to be exposed, you're safe from the latter issue. If you wrap all your code that uses new and delete in a class (ie using RAII) then you're pretty safe from the former too.
Avoiding memory leaks in C++ is very easy if you do the above.
Two simple rules of thumb:
Never call delete explicitly (outside a RAII class, that is). Every memory allocation should be the responsibility of a RAII class which calls delete in the destructor.
Almost never call new explicitly. If you do, you should immediately wrap the resulting pointer in a smart pointer, which takes ownership of the allocation, and works as above.
In your own RAII classes, two common pitfalls are:
Failure to handle copying correctly: Who takes ownership of the memory if the object is copied? Do they create a new allocation? Do you implement both copy constructor and assignment operator? Does the latter handle self assignment?
Failure to consider exception safety. What happens if an exception is thrown during an operation (an assignment, for example)? Does the object revert to a consistent state? (it should always do this, no matter what) Does it roll back to the state it had before the operation? (it should do this when possible) std::vector has to handle this, during push_back for example. It might cause the vector to resize, which means 1) a memory allocation which may throw, and 2) all the existing elements have to be copied, each of which may throw. An algorithm like std::sort has to deal with it too. It has to call a user-supplied comparer, which could potentially throw too! if that happens, is the sequence left in a valid state? Are temporary objects destructed cleanly?
If you handle the above two cases in your RAII classes, it is pretty much impossible for them to leak memory.
And if you use RAII classes to wrap all resource allocations (memory allocations, file handles, database connections and any other type of resource that has to be acquired and released), then your application can not leak memory.
Make sure shared memory created by your application is freed if nobody's using it anymore, clean up memory mapped files...
Basically, make sure you clean up any type of resource your application directly or indirectly creates. File descriptors are only one type of resource your application may use during runtime.
if you make any tree or graph recursively in your code for your data structure maybe eat all of your memory.
There are static code analysis tools available that do this sort of thing; wikipedia is a good place to start looking. Basically, outside of being careful and choosing the correct containers you can not make guarantees about the code you write - hence the need for tools such as valgrind and gdb.
Incorporate valgrind unit and system testing early in your development cycle and use it consistantly.

Should I delete vector<string>?

I've painfully learned during last few days a lot about programming in c++.
I love it :)
I know I should release memory - the golden "each malloc=free" or "each new=delete" rules exist now in my world, but I'm using them to rather simple objects.
What about vector ? Wherever I can, I'm using vector.clear() but that clearly isn't enough, because I'm having huge memory leaks.
Could you guide me on how should I treat this thing?
*Edit
Thanks, your comments made me think about the alghorithm of this application and I'll be able to eliminate the vector totally. :O
Sorry - I started explaining what is my use case here and I found out what I really need. It's like that when you code last 3 days for 18 hours a day :|
*Edit 2
This is crazy. By small changes in code, I've eliminated memory usage from 2x130 mb (constantly growing) into 2x 13,5mb, constant size. Thanks for making me think about that in another way.
Btw. such self code review got a name - anyone remember that? It's when you ask anyone (even your mother or dog) and start explaining what's your problem - and suddenly you solve this 5 hour problem yourself, just by trying to look at it from other point of view, or just by trying to summarize what's it all about. I often find myself being catched on that...
The rule is that when you clear a vector of objects, the destructor of each element will be called. On the other hand, if you have a vector of pointers, vector::clear() will not call delete on them, and you have to delete them yourself.
So if all you have is a vector of strings, and not pointers to strings, then your memory leaks must be caused by something else.
You don't need to be doing this. std::string cleans itself up, so the strings are not your problem. Remember that YOU didn't use new so YOU don't have to use delete.
You should probably learn about RAII - it makes allocation and deallocation much simpler. You'll avoid memory leaks this way.
Calling v.clear() will destroy all objects that are currently held inside v, but it will not release the memory (it is assumed that the vector will soon be filled again).
If you really want to free the memory, the idiom is
vector<string>().swap(v);
This will create a new (temporary) vector and swap its contents with v. The temporary vector is then destroyed, freeing the memory along with it.
Deleting elements from STL containers is guaranteed to call destructors on these elements.
However, if you have a container of some pointer-to-T type, then you still have to free the pointed-to memory yourself (in this case, the "destructor" for the pointer gets called, which is a no-operation).
If you do not want to manually manage memory in this case, consider using a smart-pointer solution or a pointer container.
The vector (like all standard containers) owns the objects inside it.
So it is responsible for destroying them.
Note: If you vector contains pointers then it owns the pointers (not what the pointers point at). So these need to be deleted. But there are easier ways.
You could use a vector of smart pointers. In fact you should be using some form of smart pointer for nearly everything. If you are using pointers you are probably still programming like a C programmer.
So:
std::vector<int> data; // clear is fine.
std::vector<int*> data1; // Now things need to be deleted.
// alternative 1:
std::vector<boost::shared_ptr<int> > data2; // The shared pointer will auto
// delete the pointer.
// alternative 2:
boost::ptr_vector<int> data3; // Here the container knows that
// it is holding pointers and will
// auto de-reference them when you
// its members.
But it sounds like you need to start thinking about learning about smart pointers.
int* x = new int(5);
// Do stuff.
*x = 8;
delete x;
// --- Instead use a smart pointer:
std::auto_ptr<int> x(new int(5));
// Do stuff.
*x = 8;
// No delete (the auto ptr handles it.
If you have a vector and it goes out of scope, all objects in the vector are destroyed. There isn't really a need to call clear() unless you want to dump the contents and reuse the vector.
However if you by any chance are using something like a vector then the destructor of the objects being pointed to will not be called as the vector destructor doesn't follow the indirections represented by the pointers.
All that said, have you actually confirmed that you've got genuine memory leaks and that they are caused by the data in the vector?
Give a use case. The destructor on the string is getting called by vector::clear. Your problem lies elsewhere my friend.
also check out:
Does std::vector.clear() do delete (free memory) on each element?
As rlbond suggested, use RAII.
It's a good rule of thumb to never put new and delete calls into your main code flow. Always try to put them into objects so that the object destructor can free what needs to be freed. In this way, you avoid needing to remember to call delete and it makes your code exception safe (assuming that you make your object's operations exception safe).
For example, if you had a vector of pointers to STL strings or C-style character arrays, put that into a StringContainer (use a better name) and have the StringContainer hold a vector and in the StringContainer destructor run a for loop to delete each string in the vector.
You can make the vector inside the StringContainer a public member and mess around with it directly, but it's even better design to make it private or protected and add some member functions to manage the string* vector.
So your main C++ program should never see a new or delete anywhere. Instead it should have a lot of stack allocated objects, auto_ptrs and shared_ptrs.