views:

412

answers:

14

I am pretty proficient with C, and freeing memory in C is a must.

However, I'm starting my first C++ project, and I've heard some things about how you don't need to free memory, by using shared pointers and other things.

Where should I read about this? Is this a valuable replacement for proper delete C++ functionality? How does it work?

EDIT

I'm confused, some people are saying that I should allocate using new and use smart pointers for the deallocation process.

Other people are saying that I shouldn't allocate dynamic memory in the first place.

Others are saying that if I use new I also have to use delete just like C.

So which method is considered more standard and more-often used?

+16  A: 

Where should I read about this?

Herb Sutter's Exceptional C++ and Scott Meyers's More Effective C++ are both excellent books that cover the subject in detail.

There is also a lot of discussion on the web (Google or StackOverflow searches for "RAII" or "smart pointer" will no doubt yield many good results).

Is this a valuable replacement for proper delete C++ functionality?

Absolutely. The ability not to worry about cleaning up resources, especially when an exception is thrown, is one of the most valuable aspects of using RAII and smart pointers.

James McNellis
RAII can be implemented in terms of `new`/`delete`. Put new in constructor, `delete` in destructor. Using smart pointers is another way to handle RAII.
Brian
+1  A: 

Freeing memory in C++ is just as much a must as in C.

What you may be thinking of is a smart pointer library (the standard library's auto_ptr among others) - which will do reference counting for you.

Alex DeLarge
STL is not a part of standard C++? Since when?
Jeremy Friesner
auto_ptr is part of standard C++, however its not the most useful smart pointer.
jk
@Jeremy: Strictly speaking C++ has no concept of STL. It has a standard library. STL may refer to several things, and is generally ambiguous. That said, I agree Alex's answer is worded strange, and could be read as saying `auto_ptr` isn't standard.
GMan
@Jeremy - STL is not a part of the standard C++ language specification, hence the L (library) part of the acronym.Agreed I did not word the response correctly and have edited it.
Alex DeLarge
+2  A: 

Well, of course you need to delete. I would rephrase this as 'what libraries can I use that can automate the deletion of allocated memory?'. I'd recommend you start by reading up the Boost Smart pointers page.

Remus Rusanu
+1  A: 

Since C++ does not have a garbage collector built into the language, you need to be aware of what memory you have dynamically allocated and how that memory is being freed.

That said, you can use smart pointers to alleviate the problem of having to manually free memory via delete - for example, see Smart Ponters (boost).

Justin Ethier
+4  A: 

You still have to worry about freeing memory in C++, it's just that there are better methods/tools for doing so. One can argue that attention to memory management in C++ is more difficult as well due to the added requirement of writing exception safe code. This makes things such as:

MyClass *y = new MyClass;
doSomething(y);
delete y;

Look completely harmless until you find that doSomething() throws an exception and now you have a memory leak. This becomes even more dangerous as code is maintained as the code above could have been safe prior to someone changing the doSomething() function in a later release.

Following the RAII methodology is a big part of fixing memory management challenges and using auto_ptr's or shared pointers provided by libraries such as Boost make it easier to incorporate these methods into your code.

Note that auto_ptr is not a "shared" pointer. It is an object that takes ownership of the dynamically allocated object and gives that ownership away on assignment and copy. It doesn't count references to the memory. This makes it unsuitable for use within standard containers and many in general prefer the shared_ptr of Boost to the auto_ptr provided by the standard.

It is never safe to put auto_ptrs into standard containers. Some people will tell you that their compiler and library compiles this fine, and others will tell you that they've seen exactly this example recommended in the documentation of a certain popular compiler; don't listen to them.

The problem is that auto_ptr does not quite meet the requirements of a type you can put into containers, because copies of auto_ptrs are not equivalent. For one thing, there's nothing that says a vector can't just decide to up and make an "extra" internal copy of some object it contains. For another, when you call generic functions that will copy elements, like sort() does, the functions have to be able to assume that copies are going to be equivalent. At least one popular sort internally takes a copy of a "pivot" element, and if you try to make it work on auto_ptrs it will merrily take a copy of the pivot auto_ptr object (thereby taking ownership and putting it in a temporary auto_ptr on the side), do the rest of its work on the sequence (including taking further copies of the now-non-owning auto_ptr that was picked as a pivot value), and when the sort is over the pivot is destroyed and you have a problem: At least one auto_ptr in the sequence (the one that was the pivot value) no longer owns the pointer it once held, and in fact the pointer it held has already been deleted!

Taken From: Using auto_ptr Effectively

RC
+4  A: 

If you allocate dynamic memory (with new), you need to free it (with delete), just like using malloc/free in C. The power of C++ is that it gives you lots of ways of NOT calling new, in which case you don't need to call delete.

Chris Dodd
+2  A: 

Looks like Question: Pointers, smart pointers or shared pointers?

rubber boots
+1  A: 

First and foremost, before you get into the business of using auto_ptr's and writing your own RAII classes, learn to use the Standard Template Library. It provides many common container classes that automatically allocate their internal memory when you instantiate them and free it up when they go out of scope - things like vectors, lists, maps, and so forth. When you employ STL, using the new-operator and delete (or malloc and free) is rarely necessary.

Jive Dadson
+2  A: 

The best answer I can give you is: something needs to call delete for each object created with new. Whether you do it manually, or using a scope-based smart pointer, or a reference-counted smart pointer, or even a non-deterministic garbage collector, it still needs to be done.

Having said that, I have not manually called delete in 10 years or so. Whenever I can I create an automatic object (on the stack); when I need to create an object on the heap for some reason I try using a scope-based smart pointer, and in rare cases when there is a legitimate reason to have shared ownership, I use a reference counted smart pointer.

Nemanja Trifunovic
A: 

'm confused, some people are saying that I should allocate using new and use smart pointers for the deallocation process.

They're right. Just like in C you still need to manage all your memory one way or another. however there are ways to use the language to automate delete.

Smart pointers are basically local scope wrappers for pointers which use the object .dtor to delete the corresponding pointer once the smart pointer - which is like any other objecton the stack - goes out of scope

Nick
+8  A: 

What I meant in my comment (sorry for being terse - I had to run out to the shops) is that you should be using:

std::string s = "foobar";

rather than:

std::string * s = new std::string( "foobar" );
...
delete s;

and:

vector <Person> p;
p.push_back( Person( "fred" ) );

rather than:

vector <Person *> p;
p.push_back( new Person( "fred" ) );

You should always be using classes that manage memory for you. In C++ the main reason for creating an object using new is that you don't know its type at compile-time. If that isn't the reason, think long and hard before using new and delete, or even smart pointers.

anon
... Or `vector<shared_ptr<Person> > p;`
greyfade
@greyfade: Only if actually needed.
GMan
And of course, use `vector` rather than using a dynamically allocated array, which is what you would have probably done in C. Similarly, use `string` rather than using `char *`; though the latter does not always require dynamic allocation, things get annoying when you want to concatenate character arrays in C, at least compared to concatenating `string`s in c++.
Brian
A: 

The beauty of C++ is that you have explicit control over when things are created and when things are destroyed. Do it right and you will not have issues with memory leaks etc.

Depending on your environment, you may want to create objects on the stack or you may want to dynamically allocated (create them on the 'heap' - heap in quotes because its an overused term but is good enough for now).

Foo x; // created on the stack - automatically destroyed when the program exits that block of code it was created in.

Foo *y = new Foo; // created on the heap - its O.K. to pass this one around since you control when its destroyed

Whenever you use 'new', you should use the corresponding version of delete... somewhere, somehow. If you use new to initialize a smart pointer like:

std::auto_ptr x = new Foo;

You are actually creating two items. An instance of auto_ptr and an instance of Foo. auto_ptr is created on the stack, Foo on the heap.

When the stack 'unwinds', it will automatically call delete on that instance of Foo. Automatically cleaning it up for you.

So, general rule of thumb, use the stack version whenever possible/practical. In most instances it will be faster as well.

con_fuse9
+2  A: 

This is a great question, and actually several in one:

Do I need to worry about Managing Memory?

Yes! There is no garbage collection in C++. Anytime you allocate something with new you need to either call delete in your own code, or delegate that responsibility to something like a smart pointer.

When Should I use dynamic memory allocation?

The reasons you'd want to use dynamic memory allocation (allocating with new). Some of these include:

  • You don't know the size of the thing you are allocating at compile time
  • You don't know the type of the thing you are allocating at compile time
  • You are reusing the same data in different contexts and don't want to pay the performance overhead of copying that data around.

There are lots of other reasons, and these are gross over generalizations, but you get the idea.

What tools can I use to help me with memory management?

Smart pointers are the way to go here. A smart pointer will take ownership of memory that you allocate, and then release that memory automatically for you at a specific time depending on the policy the smart pointer.

For example, a boost::scoped_ptr will deallocate memory for you when it goes out of scope

{
   scoped_ptr<MyClass> myVar( new MyClass() );

   // do Something with myVar

} // myVar goes out of scope and calls delete on its MyClass

In general you should use smart pointers over raw pointers anytime you can. It will save you years of tracking down memory leaks.

Smart pointers come in many forms including:

If you can use Boost smart pointers I would. They rock!

Nick Haddad
A: 

In order of preference, you should:

  1. Avoid handling allocation yourself at all. C++'s STL (standard template library) comes with a lot of containers that handle allocation for you. Use vector instead of dynamically allocated arrays. Use string instead of char * for arrays of characters. Try to seek out an appropriate container from the STL rather than designing your own.

  2. If you are designing your own class and honestly need dynamic allocation (and you usually won't if you compose your class using members of the STL), place all instances of new (new[]) in your constructor and all instances of delete (delete[]) in your destructor. You shouldn't need malloc and free, generally.

  3. If you are unable to keep your allocations paired within constructors and destructors, use smart pointers. Really this is not so different from #2; smart pointers are basically just special classes which use destructors to ensure deallocation happens.

Brian
As an aside: Part of my reason for prefering 2 over 3 is that any smart pointer not included with C++ (e.g. Boost) should not be considered "standard," imo. And you can't use `auto_ptr` in an STL container.
Brian
If one can't use Boost, at least replicate `shared_ptr` and friends. Then you don't need to waste time writing a copy-constructor, copy assignment operator, and destructor. The only time I do those is when making a small utility class so I don't need to do it anymore in that use case.
GMan