I'm coming from a Java background and have started working with objects in C++. But one thing that occurred to me is that people often use pointers to objects rather than the objects themselves, for example this declaration:
Object *myObject = new Object;
rather than:
Object myObject;
Or instead of using a function, let's say testFunc()
, like this:
myObject.testFunc();
we have to write:
myObject->testFunc();
But I can't figure out why should we do it this way. I would assume it has to do with efficiency and speed since we get direct access to the memory address. Am I right?
There are many use cases for pointers.
Polymorphic behavior. For polymorphic types, pointers (or references) are used to avoid slicing:
Reference semantics and avoiding copying. For non-polymorphic types, a pointer (or a reference) will avoid copying a potentially expensive object
Note that C++11 has move semantics that can avoid many copies of expensive objects into function argument and as return values. But using a pointer will definitely avoid those and will allow multiple pointers on the same object (whereas an object can only be moved from once).
Resource acquisition. Creating a pointer to a resource using the
new
operator is an anti-pattern in modern C++. Use a special resource class (one of the Standard containers) or a smart pointer (std::unique_ptr<>
orstd::shared_ptr<>
). Consider:vs.
A raw pointer should only be used as a "view" and not in any way involved in ownership, be it through direct creation or implicitly through return values. See also this Q&A from the C++ FAQ.
More fine-grained life-time control Every time a shared pointer is being copied (e.g. as a function argument) the resource it points to is being kept alive. Regular objects (not created by
new
, either directly by you or inside a resource class) are destroyed when going out of scope.A pointer directly references the memory location of an object. Java has nothing like this. Java has references that reference the location of object through hash tables. You cannot do anything like pointer arithmetic in Java with these references.
To answer your question, it's just your preference. I prefer using the Java-like syntax.
In areas where memory utilization is at its premium , pointers comes handy. For example consider a minimax algorithm, where thousands of nodes will be generated using recursive routine, and later use them to evaluate the next best move in game, ability to deallocate or reset (as in smart pointers) significantly reduces memory consumption. Whereas the non-pointer variable continues to occupy space till it's recursive call returns a value.
It's very unfortunate that you see dynamic allocation so often. That just shows how many bad C++ programmers there are.
In a sense, you have two questions bundled up into one. The first is when should we use dynamic allocation (using
new
)? The second is when should we use pointers?The important take-home message is that you should always use the appropriate tool for the job. In almost all situations, there is something more appropriate and safer than performing manual dynamic allocation and/or using raw pointers.
Dynamic allocation
In your question, you've demonstrated two ways of creating an object. The main difference is the storage duration of the object. When doing
Object myObject;
within a block, the object is created with automatic storage duration, which means it will be destroyed automatically when it goes out of scope. When you donew Object()
, the object has dynamic storage duration, which means it stays alive until you explicitlydelete
it. You should only use dynamic storage duration when you need it. That is, you should always prefer creating objects with automatic storage duration when you can.The main two situations in which you might require dynamic allocation:
When you do absolutely require dynamic allocation, you should encapsulate it in a smart pointer or some other type that performs RAII (like the standard containers). Smart pointers provide ownership semantics of dynamically allocated objects. Take a look at
std::unique_ptr
andstd::shared_ptr
, for example. If you use them appropriately, you can almost entirely avoid performing your own memory management (see the Rule of Zero).Pointers
However, there are other more general uses for raw pointers beyond dynamic allocation, but most have alternatives that you should prefer. As before, always prefer the alternatives unless you really need pointers.
You need reference semantics. Sometimes you want to pass an object using a pointer (regardless of how it was allocated) because you want the function to which you're passing it to have access that that specific object (not a copy of it). However, in most situations, you should prefer reference types to pointers, because this is specifically what they're designed for. Note this is not necessarily about extending the lifetime of the object beyond the current scope, as in situation 1 above. As before, if you're okay with passing a copy of the object, you don't need reference semantics.
You need polymorphism. You can only call functions polymorphically (that is, according to the dynamic type of an object) through a pointer or reference to the object. If that's the behaviour you need, then you need to use pointers or references. Again, references should be preferred.
You want to represent that an object is optional by allowing a
nullptr
to be passed when the object is being omitted. If it's an argument, you should prefer to use default arguments or function overloads. Otherwise, you should prefer use a type that encapsulates this behaviour, such asstd::optional
(introduced in C++17 - with earlier C++ standards, useboost::optional
).You want to decouple compilation units to improve compilation time. The useful property of a pointer is that you only require a forward declaration of the pointed-to type (to actually use the object, you'll need a definition). This allows you to decouple parts of your compilation process, which may significantly improve compilation time. See the Pimpl idiom.
You need to interface with a C library or a C-style library. At this point, you're forced to use raw pointers. The best thing you can do is make sure you only let your raw pointers loose at the last possible moment. You can get a raw pointer from a smart pointer, for example, by using its
get
member function. If a library performs some allocation for you which it expects you to deallocate via a handle, you can often wrap the handle up in a smart pointer with a custom deleter that will deallocate the object appropriately.This is has been discussed at length, but in Java everything is a pointer. It makes no distinction between stack and heap allocations (all objects are allocated on the heap), so you don't realize you're using pointers. In C++, you can mix the two, depending on your memory requirements. Performance and memory usage is more deterministic in C++ (duh).
I will compare how it works inside the function body if you use:
Inside the function, your
myObject
will get destroyed once this function returns. So this is useful if you don't need your object outside your function. This object will be put on current thread stack.If you write inside function body:
then Object class instance pointed by
myObject
will not get destroyed once the function ends, and allocation is on the heap.Now if you are Java programmer, then the second example is closer to how object allocation works under java. This line:
Object *myObject = new Object;
is equivalent to java:Object myObject = new Object();
. The difference is that under java myObject will get garbage collected, while under c++ it will not get freed, you must somewhere explicitly call `delete myObject;' otherwise you will introduce memory leaks.Since c++11 you can use safe ways of dynamic allocations:
new Object
, by storing values in shared_ptr/unique_ptr.also, objects are very often stored in containers, like map-s or vector-s, they will automatically manage a lifetime of your objects.