views:

450

answers:

8

Hi folks, I'm a c and java programmer, so memory allocation and OOP aren't anything new to me. But, I'm not sure about how exactly to avoid memory leaks with C++ implementation of objects. Namely:

string s1("0123456789");
string s2 = s1.substr(0,3);

s2 now has a new string object, so it must be freed via:

delete &s2;

Right?

Moreover, am I correct to assume that I'll have to delete the address for any (new) object returned by a function, regardless of the return type not being a pointer or reference? It just seems weird that a object living on the heap wouldn't be returned as a pointer when it must be freed.

+12  A: 

No,

both s1 and s2 will get destructed when out of scope.

s1.substr() will create a temporary object that you don't have to think of

Joakim Elofsson
s1 and s2 get destructed when they go out of scope, not deleted.
bk1e
corrected thanks
Joakim Elofsson
+1  A: 

why do you have to free s2 manually? deletion of dynamic memory in s2 will be handled by the std::string destructor.

oykuo
He wants an answer, not another question.
Tom Leys
Ok, I removed the question mark at the end :)
oykuo
+1  A: 

No, s2 does not need to be manually deleted. It is a local variable on the stack that will get automatically destroyed once it goes out of scope, just as it was automatically allocated when it was declared. Generally you only delete things that you allocated with new.

Temporary objects returned by functions are managed automatically and get destroyed by the end of the statement - if they are needed longer they get usually copied to a local variable before the temporary is destroyed (e.g. by a simple assignment like Object o = f(); or like in the line with the substr() call in your example).

If a function returns a pointer, the pointed-to object is not automatically managed like this. In the documentation should be noted who is responsible to delete the object once all work is done. As a default convention usually the one who allocated the object is responsible to delete it again, but the details need to be documented somewhere.

sth
Most common objects are deleted within destruction, so you don't need to explicitly delete them.
Luca Matteis
+6  A: 

Both s1 and s2 are auto allocated. You don't delete those. You only delete objects which you have created using new.

C++ knows three allocation modes: auto, static and dynamic. Read up on those. Auto values, like your strings in the example are freed automatically when they leave scope. Their destructor is called automatically. Any memory that the strings allocated dynamically during their operation is freed when the string destructor is called.

haffax
+14  A: 

No.

You only need to free memory you allocate (i.e. via new or memalloc).

Burkhard
+1 for being straight to the point
Gab Royer
+3  A: 

Like everyone else said - no delete is needed here. Unless you see a new, you (generally) don't need a delete. I do want to add that s2 doesn't have a new string object. s2 is a string object from the time that it is declared. Assigning a slice of s1 to s2 modifies s2 so that it contains the same characters that are in the substring.

It's really important to understand what is going on here and it will become even more important the more you dig into C++. Oh, and congrats on learning a new language.

D.Shawley
+1  A: 

One of the most important concepts to understand in modern C++ (especially coming from a c background) is RAII. C++ encapsulates resources like memory (or mutexes, or transactions) inside classes that "acquire" the resource on construction (the string constructor allocates dynamic memory) and "release" it on destruction (destruction of the string class frees it). Since destruction of stack objects is deterministic (the stack based object expires when the enclosed scope does), the release doesn't have to be written, and will happen even if an exception is thrown.

So, no. In most of my coding, I never have a write an explicit delete (or delete[]), because either the resources are managed by string, an STL conatiner, or a shared_ptr or scoped_ptr.

Todd Gardner
+5  A: 

There are a couple of layers to the answers.

First, variables can be declared in several different ways:

  • as local variables (either inside a function or as class members). Examples: int i, or int i = 42. These have automatic storage duration (these examples are technically shorthand for auto int i, or auto int i = 42, although the auto keyword is virtually never used. What this means is that these variables will be automaticaly freed when they go out of scope. Their destructor is guaranteed to be called (no matter how you leave the scope, whether it is by a function return or by throwing an exception, their destructor will be called when they go out of scope, and then the memory they use is freed). Local variables declared like this are allocated on the stack.
  • as static variables (with the static keyword, implying static storage duration, as opposed to automatic shown above. These just stay around for the duration of the program, and so don't have to be freed
  • on the heap, with dynamic allocation (new int or new int(42)). These have to be freed manually by calling delete.

So at the lowest level, you basically just have to preserve symmetry. If something was allocated with new, free it with delete, malloc is freed by free, and new[] by delete[]`. And variables that are declared without any of these are automatically handled, and should not be manually freed.

Now, to keep memory management simple, RAII is typically used. The technique is based on the observation that only dynamically allocated objects have to be manually freed, and that local variables give you a very convenient hook for implementing custom actions when a local variable goes out of scope. So the dynamic allocation is wrapped up inside a separate class, which can be allocated as a local object on the stack. It can then, in its constructor, make any dynamic allocations you need, and its destructor cleans it up with the necessary delete calls.

This means that you essentially never have to call delete in your top-level code. It'll virtually always be hidden behind a RAII object's destructor. new calls become rare too, but are still used together with smart pointers (such as this: boost::shared_ptr<int>(new int(42)) which dynamically allocates an integer, and then passes it to a smart pointer which takes over ownership of it, and cleans it up automatically.

jalf
+1 - very thorough answer. I especially liked the RAII mention and the fact that you left that nasty auto_ptr<> out of the description.
D.Shawley