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::vectoris 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 (withdelete result) to avoid leaking its memory. The thing is made complicated because of exceptions, that can alter your return path and skip anydeleteyou 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 bestd::vectorimplementations that implement copy-on-write optimization like manystd::stringimplementations 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(orstd::unique_ptrin C++0x), and also change the return type of your function tostd::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 thevectorif its still owned by it. Also, it’s completely clear who owns the returned object.Make the
resultvector 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_inserteror 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.