When looking at your code sample there are 3 options that come to mind where any of them could be viable options; let's explore these options below.
Raw pointer
shared_ptr<T>
unique_ptr<T>
Each of these have their own cons & pros in their usage.
Since you are using raw
in your example; I'll start with that one first:
raw
Pro:
- You have the flexibility to manage the memory your self, but it comes at the cost of a higher responsibility.
Con:
- It is prone to memory leaks, dangling & invalid pointers.
shared_ptr
Pro:
- Manages the memory for you; and is accessible across multiple objects as it is shared memory via reference counting.
Con:
- It is based on the assumption that you will never face a memory leak or dangling pointer just because of using this smart pointer where it is not always guaranteed to be released but usually is in most cases. Sometimes you may not want a pointer to be accessible across multiple objects. It also has a small performance hit from reference counting.
unique_ptr
Pro:
- Nearly same as above only that one object can own this providing more protection of unwanted access.
Con:
- Similar as above under the assumption that the memory will always be freed. If the functionality needed does require multiple objects or sources to access this at some future point in time, then you are limited by using this type of pointer. You can transfer ownership but you can not access via multiple objects.
In the end it comes down to your particular need of which type you will want to use. In your particular situation there is nothing wrong with using raw pointers within the class if they are private members
but you have more work to manage the class and more to be conscience of when dealing with the allocation & releasing of memory. If using unique_ptr
then it is a matter of knowing if the memory object will be strictly internal to the pertaining class object or not. If using shared_ptr
then it is a matter of knowing which external objects will be referencing it.
In the end you had asked:
What kind of pointer should I use?
Taking the knowledge from the above information and by understanding the type of object you are working with, let's consider what the BST does or is responsible for and its primary role as a class object.
We know that it is a Binary Space Partitioning Tree
typically used with a Binary Search
. Where one is the data structure
and the other is the searching algorithm
.
It is a tree that consists of a set of nodes
and each node
has 2 leaf nodes
. The very first node
in the tree is typically called the root
or the head
where a leaf node that has no data or is empty
a terminating node
is normally called the tail
and is usually set to null
or nullptr
. We can see the relationship of these nodes and know that the BST
will have ownership
of at least the root
node. This way each instance of a BST
object will be unique from another. Example:
BST tree1; // Tree 1
BST tree2; // Tree 2
// Not valid code below but shown to illustrate a concept
tree1.root != tree2.root; // These two roots are not equal as in not the same memory.
This is what we would want to keep one tree unique from another and because of this behavior we really wouldn't want to use shared_ptr
. With this particular class I think the better option here if not using raw pointers
and managing your own memory and using smart pointers to show ownership
and uniqueness
between multiple objects that unique_ptr
would then be the one to choose.
When designing classes and trying to decide which smart pointer
to use these are the basic questions you should ask & answer yourself:
- Does this object
have a
? If yes; does it solely own it or does each instance's internal memory need to be unique? If Yes; then use a unique_ptr
- Does this object have to be referenced across multiple objects? If yes, then use
shared_ptr
.
Here are a few references: One from a paper and another from and Q/A, one from code review:
These references may also help you into making a well defined decision.