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?
Something that I haven't seen mentioned is the increased memory usage. Assuming 4 byte integers and pointers
will use 8 bytes, and
will use 12 bytes, a 50% increase. It doesn't sound like a lot until you allocate enough for a 512x512 image. Then you are talking 2MB instead of 3MB. This is ignoring the overhead of managing the heap with all of these object on them.
A good general rule of thumb is to NEVER use new unless you absolutely have to. Your programs will be easier to maintain and less error prone if you don't use new as you don't have to worry about where to clean it up.
Object lifetime. When you want the lifetime of your object to exceed the lifetime of the current scope, you must use the heap.
If on the other hand, you don't need the variable beyond the current scope, declare it on the stack. It will automatically be destroyed when it goes out of scope. Just be careful passing its address around.
The best reason not to new everything is that you can very deterministic cleanup when things are on the stack. In the case of Pixel's this is not so obvious, but in the case of say a file, this becomes advantageous:
In the case of newing a file, you would have to remember to delete it to get the same behavior. Seems like a simple issue in the above case. Consider more complex code, however, such as storing the pointers into a data structure. What if you pass that data structure to another piece of code? Who is responsible for the cleanup. Who would close all your files?
When you don't new everything, the resources are just cleaned up by the destructor when the variable goes out of scope. So you can have greater confidence that resources are successfully cleaned up.
This concept is known as RAII -- Resource Allocation Is Initialization and it can drastically improve your ability to deal with resource acquisition and disposal.
The question is: why would you use pointers for everything? Stack allocated objects are not only safer and faster to create but there is even less typing and the code looks better.
Basically, when you use raw pointers, you do not have RAII.