Suppose that I define some class:
class Pixel {
public:
Pixel(){ x=0; y=0;};
int x;
int y;
}
Then write some code using it. Why would I do the following?
Pixel p;
p.x = 2;
p.y = 5;
Coming from a Java world I always write:
Pixel* p = new Pixel();
p->x = 2;
p->y = 5;
They basically do the same thing, right? One is on the stack while the other is on the heap, so I'll have to delete it later on. Is there any fundamental difference between the two? Why should I prefer one over the other?
The code:
does no dynamic allocation of memory - there is no searching for free memory, no updating of memory usage, nothing. It is totally free. The compiler reserves space on the stack for the variable at compile time - it works out have much space to reserve and creates a single opcode to move the stack pointer the required amount.
Using new requires all that memory management overhead.
The question then becomes - do you want to use stack space or heap space for your data. Stack (or local) variables like 'p' require no dereferencing whereas using new adds a layer of indirection.
I'd say it's a lot about a matter of taste. If you create an interface allowing methods to take pointers instead of references, you are allowing the caller to pass in nil. Since you allow the user to pass in nil, the user will pass in nil.
Since you have to ask yourself "What happens if this parameter is nil?", you have to code more defensively, taking care of null checks all the time. This speaks for using references.
However, sometimes you really want to be able to pass in nil and then references are out of the question :) Pointers give you greater flexibility and allow you to be more lazy, which is really good. Never allocate until know you have to allocate!
They are not the same until you add the delete.
Your example is overly trivial, but the destructor may actually contain code that does some real work. This is referred to as RAII.
So add the delete. Make sure it happens even when exceptions are propagating.
If you had picked something more interesting like a file (which is a resource that needs to be closed). Then do it correctly in Java with pointers you need to do this.
The same code in C++
Though people mention the speed (because of finding/allocating memory on the heap). Personally this is not a deciding factor for me (the allocators are very quick and have been optimized for C++ usage of small objects that are constantly created/destroyed).
The main reason for me is object life time. A locally defined object has a very specific and well defined lifetime and the the destructor is guaranteed to be called at the end (and thus can have specific side effects). A pointer on the other hand controls a resource with a dynamic life span.
The main difference between C++ and Java is:
The concept of who owns the pointer. It is the responsibility of the owner to delete the object at the appropriate time. This is why you very rarely see raw pointers like that in real programs (as there is no ownership information associated with a raw pointer). Instead pointers are usually wrapped in smart pointers. The smart pointer defines the semantics of who owns the memory and thus who is responsible for cleaning it up.
Examples are:
There are others.
Use pointers and dynamically allocated objects ONLY WHEN YOU MUST. Use statically allocated (global or stack) objects wherever possible.
To clarify, by 'static' in this context, I mean non-dynamically allocated. IOW, anything NOT on the heap. Yes, they can have object lifetime issues too - in terms of singleton destruction order - but sticking them on the heap doesn't usually solve anything.
Objects created on the stack are created faster than objects allocated.
Why?
Because allocating memory (with default memory manager) takes some time (to find some empty block or even allocate that block).
Also you don't have memory management problems as the stack object automatically destroys itself when out of scope.
The code is simpler when you don't use pointers. If your design allows you to use stack objects, I recommend that you do it.
I myself wouldn't complicate the problem using smart pointers.
OTOH I have worked a little in the embedded field and creating objects on the stack is not very smart (as the stack allocated for each task/thread is not very big - you must be careful).
So it's a matter of choice and restrictions, there is no response to fit them all.
And, as always don't forget to keep it simple, as much as possible.
First case is best unless more members are added to Pixel class. As more and more member gets added, there is a possibility of stack overflow exception