views:

4686

answers:

7

Hi all,

I'm a C programmer trying to understand C++. Many tutorials demonstrate object instantiation using a snippet such as:

Dog* sparky = new Dog();

which implies that later on you'll do:

delete sparky;

which makes sense. Now, in the case when dynamic memory allocation is unnecessary, is there any reason to use the above instead of

Dog sparky;

and let the destructor be called once sparky goes out of scope?

Thanks!

+7  A: 

Well, the reason to use the pointer would be exactly the same that the reason to use pointers in C allocated with malloc: if you want your object to live longer than your variable!

It is even highly recommended to NOT use the new operator if you can avoid it. Especially if you use exceptions. In general it is much safer to let the compiler free your objects.

PierreBdR
+3  A: 

The only reason I'd worry about is that Dog is now allocated on the stack, rather than the heap. So if Dog is megabytes in size, you may have a problem,

If you do need to go the new/delete route, be wary of exceptions. And because of this you should use auto_ptr or one of the boost smart pointer types to manage the object lifetime.

Roddy
A: 

In C++ when using new the object is created in the heap and not on the stack that has scope for the current function only - So it depends on the usage of Dog.

In case you need return a Dog value from the current function you must allocate it on the heap using the new keyword.

Note: This behavior is exactly the same as C.

Dror Helper
Uh, no: C++ can return classes by value, so "Dog getSparky() { Dog Sparky; return Sparky;}" works 100% - assuming Dog has a valid copy constructor. Returning a REFERENCE to sparky will bite you, though.
Roddy
And Personally - I would avoid Creating things on the heap in a function and then returning them, as you are never sure what will delete them later. If you have to do this there needs to be a very clear plan of what will clean up the memory later.
NotJarvis
#NotJavis if that's what you think I have another good suggestion - avoid coding at all costs because writing code can cause bugs.Seriously you have a tool - it's up to you to decide whn and how to use it, and there are instances when returning an object fomr a method is advisable - ever heard of "factory method"?
Dror Helper
+2  A: 

There's no reason to new (on the heap) when you can allocate on the stack (unless for some reason you've got a small stack and want to use the heap.

You might want to consider using a shared_ptr (or one of its variants) from the standard library if you do want to allocate on the heap. That'll handle doing the delete for you once all references to the shared_ptr have gone out of existance.

Scott Langham
+13  A: 

On the contrary, you should always prefer stack allocations, to the extent that as a rule of thumb, you should never have new/delete in your user code.

As you say, when the variable is declared on the stack, its destructor is automatically called when it goes out of scope, which is your main tool for tracking resource lifetime and avoiding leaks.

So in general, every time you need to allocate a resource, whether it's memory (by calling new), file handles, sockets or anything else, wrap it in a class where the constructor acquires the resource, and the destructor releases it. Then you can create an object of that type on the stack, and you're guaranteed that your resource gets freed when it goes out of scope. That way you don't have to track your new/delete pairs everywhere to ensure you avoid memory leaks.

The most common name for this idiom is RAII

Also look into smart pointer classes which are used to wrap the resulting pointers on the rare cases when you do have to allocate something with new outside a dedicated RAII object. You instead pass the pointer to a smart pointer, which then tracks its lifetime, for example by reference counting, and calls the destructor when the last reference goes out of scope. The standard library has std::auto_ptr for this, and boost (which you might consider the secondary standard library), you have boost::shared_ptr which does reference counting to implement shared ownership.

Many tutorials demonstrate object instantiation using a snippet such as ...

So what you've discovered is that most tutorials suck. ;) Most tutorials teach you lousy C++ practices, including calling new/delete to create variables when it's not necessary, and giving you a hard time tracking lifetime of your allocations.

jalf
Raw pointers are useful when you want auto_ptr-like semantics (transferring ownership), but retain the non-throwing swap operation, and don't want the overhead of reference counting. Edge case maybe, but useful.
Greg Rogers
This is a correct answer, but the reason I would never get into the habit of creating objects on the stack is because its never completely obvious how big that object will be. You're just asking for a stack-overflow exception.
dviljoen
Greg: Certainly. But as you say, an edge case. In general, pointers are best avoided. But they're in the language for a reason, no denying that. :)dviljoen: If the object is big, you wrap it in a RAII object, which can be allocated on the stack, and contains a pointer to heap-allocated data.
jalf
@dviljoen: No I'm not. C++ compilers don't unnecessarily bloat objects. The worst you'll see is typically that it gets rounded up to the nearest multiple of four bytes. Usually, a class containing a pointer will take as much space as the pointer itself, so it costs you nothing in stack usage.
jalf
+1  A: 

Treat heap as a very important real estate and use it very judiciously. The basic thumb rule is to use stack whenever possible and use heap whenever it is there is no other way. By allocating the objects on stack you can get many benefits such as:

(1). You need not have to worry about stack unwinding in case of exceptions

(2). You need not worry about memory fragmentation caused by the allocating more space than necessary by your heap manager.

Naveen
A: 

I've seen this anti-pattern from people who don't quite get the & address-of operator. If they need to call a function with a pointer, they'll always allocate on the heap so they get a pointer.

void FeedTheDog(Dog* hungryDog);

Dog* badDog = new Dog;
FeedTheDog(badDog);
delete badDog;

Dog goodDog;
FeedTheDog(&goodDog);
Mark Ransom