0

I encounter a strange issue when using class in C++.

Here is my code to add object the my linked list. I found that my V1 code works correct but V2 code doesn't and the printList can never stop in V2. Do anyone can explain why it is the case, since I expect V1 and V2 code should output the same outcome.

#include <iostream>

using namespace std;

class Node {
public:
    int data;
    Node *next;
    Node() {
        cout << "Node object is being created" << endl;
    }
};

void printList(Node *node) {
    while(node != NULL) {
        cout << node->data << ",";
        node = node->next;
    }
    cout << endl;
}

void push(Node **node, int data) {

    // // working V1 start
    // Node *newNode = new Node();
    // newNode->data = data;
    // newNode->next = *node;
    // *node = newNode;
    // // working V1 end

    // not working V2 start
    Node newNode;
    newNode.data = data;
    newNode.next = *node;
    *node = &newNode;
    // not working V2 end

}

int main() {
    Node *a = NULL;

    push(&a, 15);
    push(&a, 10);

    printList(a);

}
bufferoverflow76
  • 767
  • 1
  • 8
  • 23
  • Object in storage `Node newNode` stops existing as soon as execution exits the scope (method's body) where it is declared. That's basics of language. – Swift - Friday Pie May 25 '19 at 12:52

2 Answers2

2

Your V2 stores a pointer to a node in automatic storage. That node is automatically destroyed at the end of the push function at which point the pointer is left dangling and no longer points to a valid object.

When you later attempt to indirect through that pointer, the behaviour of the program is undefined.


V1 does not have this problem, since it allocates the nodes in dynamic storage. Instead, the problem with V1 is that it leaks the allocated memory. Dynamic allocations created with new-expression need to be deallocated with delete-expression.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

The second code snippet has undefined behaviour because 1) the pointer newNode is not initialized and 2) you did not allocate memory where you are going to store values data and *node.

Node newNode;
newNode.data = data;
newNode.next = *node;

In the first code snippet a memory for the new node is allocated and the pointer is initialized by the address of the allocated memory

Node *newNode = new Node();

So these statements

newNode.data = data;
newNode.next = *node;

are valid and write data to the allocated memory.

Take into account that if to define the class the following way (removing the default constructor)

class Node {
public:
    int data;
    Node *next;
};

then the function can be written much simpler

void push( Node **node, int data )
{
    *node = new Node { data, *node };
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335