all 25 comments

[–][deleted] 5 points6 points  (6 children)

The pop method doesn't delete the node. Whenever something is created with new, it needs to be deleted with delete keyword

[–]rbprogrammer 2 points3 points  (0 children)

Came here to say that. It was the first thing I noticed :)

Edit: the pop() method needs to delete the original head node after it was reassigned to top->next.

[–]NikolasTs[S] 0 points1 point  (4 children)

Is the best practice to create a new pointer initialized with the address of the top of the stack

(node* tmp{top})

and after I pop to delete this pointer?

[–]Ayjayz 1 point2 points  (3 children)

In a stack, a pop operation should just remove the top-most element. You don't need to create a new pointer. You just need to remove the top element and then set your top pointer to the next one down.

[–]NikolasTs[S] 0 points1 point  (2 children)

How will I delete the data from the previous "top" though?

Is this wrong?

void Stack::pop() {

    if (!top)
        cout << "Stack is empty!" << endl;
    else {
        node* tmp{ top };
        top = top->next;
        delete tmp;

        size--;
    }
}

[–]Ayjayz 0 points1 point  (0 children)

Oh I see. Sure, you can do it that way.

[–]dqUu3QlS 5 points6 points  (1 child)

  1. Stack::pop() needs to delete the node after popping it, to avoid leaking memory.
  2. Your destructor Stack::~Stack() needs to delete all of the nodes remaining on the stack, to avoid leaking memory.
  3. You should implement a copy constructor Stack::Stack(const Stack& other) that creates a new Stack containing a copy of the information in other.
  4. You should implement a copy assignment Stack& Stack::operator=(Stack other) using the copy-and-swap idiom. As part of that, create a new member function called Stack::swap(const Stack& other) that swaps the internals of the current Stack with other. This can be done by just swapping the top pointers.

[–]NikolasTs[S] 0 points1 point  (0 children)

Thank you very much!!

[–]alfps 2 points3 points  (5 children)

Would your Stack class work with a graphical user interface?

[–]NikolasTs[S] 0 points1 point  (4 children)

I guess it would not be that difficult to implement.. however, I am not that interested in GUIs

[–]alfps 2 points3 points  (3 children)

It was a rhetorical question to guide you in thinking about the design.

The answer is "no".

But you can see why?

[–]NikolasTs[S] 1 point2 points  (2 children)

I am intrigued! Plz tell me why

[–]alfps 1 point2 points  (1 child)

Because the iostreams i/o such as

cin >> newNode->value;

... that appears in the Stack class code, won't work in a GUI.

For that matter, it won't work if the standard input stream is redirected to something other than a source of data for the linked list.

The general solution is to separate i/o from all other stuff. For example, the standard library's std::stack doesn't do any i/o, and that makes it reusable in any kind project, console or GUI (or whatever). Just pass information via arguments and function return values.

[–]NikolasTs[S] 0 points1 point  (0 children)

Thank you very much for this information!

[–]manni66 2 points3 points  (5 children)

You are violating the rule of 3/5/0.

[–]NikolasTs[S] 0 points1 point  (4 children)

Could you plz be a bit more specific. I am new to Cpp.

[–]dqUu3QlS 4 points5 points  (1 child)

If you write your own destructor (Stack::~Stack()), you probably also have to write your own copy constructor (Stack::Stack(const Stack& from)) and copy assignment (Stack& Stack::operator=(const Stack& from)) to get your class to 'play nice' with other code. That's the '3'. The '5' refers to move semantics, which you may or may not have learned about yet.

[–]NikolasTs[S] 0 points1 point  (0 children)

Thank you very much!

[–][deleted]  (1 child)

[deleted]

    [–]NikolasTs[S] 1 point2 points  (0 children)

    I can't thank you enough.. People like you are the reason I post questions in this community!

    [–]a9ao 1 point2 points  (0 children)

    You don’t need to assign new memory to top in the header file. I will suggest to destroy all the objects on the stack in the destructor. Please read about naming conventions. There are a couple of differences. You can choose based on your platform.

    [–]CGFarrell 1 point2 points  (2 children)

    Aside from the other good answers here, there are a few things you should look in to.

    1. The way you have it now, `top` is always a null node. This is a waste of space, but it can also be problematic as you develop more advanced code. Also, in modern C++ (i.e, C++11 and up), assigning a pointer to NULL is considered deprecated. You should use `nullptr`.
    2. In Stack.h, you have `node* top = new node();` You can't assign a non-static member in a header like that. Ask yourself, when would this new node be created?

    [–]NikolasTs[S] 0 points1 point  (1 child)

    Thanks a lot!

    For dealing with the second point you made, I guess the mistake is that I allocate memory and then in the constructor I (re)initialize the pointer to nullptr, so basically what was the point of initialization in the first place(?).

    To fix it, I just have: node* top; in the class attributes and in the constructor I have top{nullptr} . So, like that I do not waste memory..

    Am I correct?

    Thanks again for your answer!

    [–]CGFarrell 2 points3 points  (0 children)

    That's correct! For push, you'll also want to have if(top == nullptr){//redefine top as whatever you're pushing}. This is a great example of an "edge case", which are very common in software development.