3

Possible duplicate
Proper stack and heap usage in C++?

I'm beginning to learn C++ from a Java background, and one big difference is the fact that I'm no longer forced to:

  1. dynamically allocate memory for objects
  2. always use pointers to handle objects

as is the case in Java. But I'm confused as to when I should be doing what - can you advise?

Currently I'm tempted to start out doing everything Java-style like

Thing *thing = new Thing();
thing->whatever();
// etc etc
Community
  • 1
  • 1

4 Answers4

5

Don't use pointers unless you know why you need them. If you only need an object for a while, allocate it on stack:

Object object;
object.Method();

If you need to pass an object to a function use references:

int doStuff( Object& object )
{
    object.Method();
    return 0;
}

only use pointers if you need

  • graph-like complex data structures or
  • arrays of different object types or
  • returning a newly created object from a function or
  • in situations when you sometimes need to specify that "there's no object" - then you use a null pointer.

If you use pointers you need to deallocate objects when those objects are no longer needed and before the last pointer to the object becomes unreacheable since C++ has no built-in garbage collection. To simplify this use smart pointers line std::auto_ptr or boost::shared_ptr.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • Or `std::tr1::shared_ptr` ;-) – Michael Krelin - hacker Sep 09 '09 at 13:08
  • 2
    Also remember that types like string and vector will be mainly heap-based, but hide all details from you. The way it should be in C++ – Paul de Vrieze Sep 09 '09 at 13:10
  • 1
    "There's no object" is better handled by `optional` – MSalters Sep 09 '09 at 13:28
  • 1
    I think you are conflating the issues of "when to use pointers" and "when to heap allocate". You can always pass a stack-allocated object by pointer, or a heap-allocated object by reference. It's not true that "if you use pointers you need to deallocate objects" - you need to deallocate objects if (and only if) (a) they're heap-allocated, (b) by you, or by someone who has given you responsibility for freeing them. Whether to heap-allocate is about the desired duration of the object, not about how you want it referred to. – Steve Jessop Sep 09 '09 at 15:29
  • I should add - nothing wrong with addressing both points, since they're both things a Java programmer needs to learn on starting with C++. But they're separate considerations. – Steve Jessop Sep 09 '09 at 15:30
3

That's bad. You're bound to forget to free it and if you're determined not to you'd have to handle exceptions because it won't get freed on stack unwinding automatically. Use shared_ptr at the very least.

shared_ptr<Thing> thing( new Thing() );
thing->whatever();

But it actually depends on the object size and the scope. If you're going to use it in one function and the object is not oversized, I'd suggest allocating it in stack frame.

Thing thing;
thing.whatever();

But the good thing is that you can decide whenever you want to allocate a new object ;-)

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
1

Do not use the new operator if you can otherwise avoid it, that way lies memory leaks and headaches remembering your object lifetimes.

The C++ way is to use stack-based objects, that cleanup after themselves when they leave scope, unless you copy them. This technique (called RAII) is a very powerful one where each object looks after itself, somewhat like how the GC looks after your memory for you in Java, but with the huge advantage of cleaning up as it goes along in a deterministic way (ie you know exactly when it will get cleaned).

However, if you prefer your way of doing objects, use a share_ptr which can give you the same semantics. Typically you'd use a shared_ptr only for very expensive objects or ones that are copies a lot.

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
1

One situation where you might need to allocate an instance on the heap is when it is only known at run-time which instance will be created in the first place (common with OOP):

 Animal* animal = 0;
 if (rand() % 2 == 0)
    animal = new Dog("Lassie");
 else
    animal = new Monkey("Cheetah");

Another situation where you might need that is when you have a non-copyable class whose instances you have to store in a standard container (which requires that its contents be copyable). A variation of that is where you might want to store pointers to objects that are expensive to copy (this decision shouldn't be done off-hand, though).

In all cases, using smart pointers like shared_ptr and unique_ptr (which are being added to the standard library) are preferable, as they manage the objects lifetime for you.

UncleBens
  • 40,819
  • 6
  • 57
  • 90
  • Factually untrue: `Animal const& animal = (rand%2) ? Dog("Lassie") : Monkey("Cheetah");` – MSalters Sep 09 '09 at 13:29
  • @MSalters Well, may-be so. Needing the object to outlive the scope where it was declared in might be a more important consideration (except one can always declare things at the top level:). However, note that your way you can only get a const reference. May-be this will change with rvalue references in C++0x. – UncleBens Sep 09 '09 at 14:21
  • @MSalters. You are missing the point. The point is that the decision is made at runtime. If you have to make the decision at runtime then you usually need to use pointers (ie dynamically allocate) (though nice trick) – Martin York Sep 09 '09 at 16:16