The linked list class definitely needs a destructor, otherwise we leak memory.
And it definitely needs a copy-constructor and assignment operator, to avoid nodes belonging to two or more lists. They can be declared = delete, but do need to exist.
The protected members are a concern. If we intend to subclass from LinkedList then we really need a virtual destructor. However, I think in this case, it's better to make the members private (the default for class types).
Users shouldn't need to know about the type Node, so it can be a class internal to LinkedList.
We should initialise m_head and currentSize in the class; then the constructor can be = default.
It doesn't make sense for the size to be negative, so use an unsigned type for that. std::size_t is the usual choice, as it should be able to represent any number of elements that can be created in our address-space.
There doesn't seem to be much point returning a bool from the add() member function, since we never return a false value (failures are reported using exceptions).
Get into the habit of using preincrement (++x) in preference to postincrement (x++) when the value doesn't matter. For many types, the former is more efficient (can save copying objects). There's no need to explicitly write this-> when accessing member variables.
If we look at your if/else, we see that they share the last statement:
if (m_head == nullptr) {
m_head = temporary;
}
else {
temporary->next = m_head;
m_head = temporary;
}
So we can move m_head = temporary to the common code path after that:
if (m_head == nullptr) {
}
else {
temporary->next = m_head;
}
m_head = temporary;
Then observe that prior to this, we set temporary->next to null, but we only need to do this for the first branch above, since the else branch immediately overwrites:
if (m_head == nullptr) {
temporary->next = nullptr;
}
else {
temporary->next = m_head;
}
m_head = temporary;
Now we see that if m_head is null, then setting next to m_head will set it to null:
if (m_head == nullptr) {
temporary->next = m_head;
}
else {
temporary->next = m_head;
}
m_head = temporary;
Which we can then write as
temporary->next = m_head;
m_head = temporary;
So the whole function now becomes
void LinkedList::add(int newEntry)
{
Node* temporary = new Node;
temporary->data = newEntry;
temporary->next = m_head;
m_head = temporary;
++currentSize;
}
And we can use aggregate initialization to set those members in the new Node object:
void LinkedList::add(int newEntry)
{
m_head = new Node{newEntry, m_head};
++currentSize;
}
This neatly solves the problem you asked about naming the new node - now it doesn't even have a name!
Updated code
#include <cstddef>
class LinkedList
{
struct Node
{
int data;
Node* next;
};
Node* m_head = nullptr;
std::size_t currentSize = 0;
public:
LinkedList() = default;
LinkedList(const LinkedList&) = delete;
void operator=(const LinkedList&) = delete;
~LinkedList() noexcept;
/** prepend the new value to the head of the list */
void add(int newEntry);
};
LinkedList::~LinkedList()
{
Node *current = m_head;
while (current) {
Node *next = current->next;
delete current;
current = next;
}
}
void LinkedList::add(int newEntry)
{
m_head = new Node{newEntry, m_head};
++currentSize;
}
.has well? \$\endgroup\$LinkedListandNodeclass definitions/implementations, so we can provide a more in-depth review than a single function. Knowing how you constructed and wrote those classes is a huge help to reviewers. \$\endgroup\$