Указатель не передает объект правильно - PullRequest
0 голосов
/ 02 июня 2018

Я пытаюсь создать стек в c ++, но, похоже, у меня проблема.

#include "stdafx.h"
#include <iostream>

using namespace std;

class Node {

public:

    int node_value;
    Node * previous_node;

};



class Stack {

public:
    Node * node_pointer;
    int size = 0;

    void push(int number) {

        Node NewNode;

        NewNode.node_value = number;
        cout << number << endl;


        if (size == 0) {

            node_pointer = &NewNode;
            cout << node_pointer << endl;
            size += 1;
            cout << "Pushed" << endl;

        }

        else if (size > 0)
        {
            NewNode.previous_node = node_pointer;
            node_pointer = &NewNode;
            cout << "Pushed" << endl;
            size += 1;
        }
    }

    void pop() {

        if (size > 1) {

            Node Temp_Node = *node_pointer;
            cout << Temp_Node.node_value << endl;
            node_pointer = Temp_Node.previous_node;
            size -= 1;
        }

        else if (size == 1){
            size -= 1;
            Node Temp = *node_pointer;
            cout << Temp.node_value;

        }

        else {
            cout << "empty" << endl;
        }

    }



};


int main()
{
    Stack stack;
    Node a;
    Node b;
    Node * p1;
    int num = 5;
    a.node_value = num;
    p1 = &a;
    b = *p1;
    cout << b.node_value << endl;
    stack.push(10);
    stack.pop();
    system("PAUSE");
    return 0;
}

Вместо того, чтобы возвращать значение узла, он возвращает адрес.Я немного сбит с толку, потому что, когда я делал то же самое только с узлами, все работало нормально.В стеке я копирую адрес в указатель node_pointer, и когда я создаю новый узел, разыменовывая указатель, он возвращает обратно совершенно разные переменные экземпляра.

Ответы [ 2 ]

0 голосов
/ 02 июня 2018

Проблема связана с функцией push (), 'newNode' является переменной в стеке, и компилятор автоматически вызывает свой деструктор в конце функции.
Чтобы избежать этого, вы должны использовать 'new'оператор для создания' newNode 'в куче, а функция pop () отвечает за освобождение памяти (используйте оператор' delete ').
Если операторы' new 'и' delete 'сбивают вас с толку, вы можетеиспользуйте вместо этого 'std :: shared_ptr'.

void push(int number) {

    Node *NewNode = new Node{};

    NewNode->node_value = number;

    if (size == 0) {

        node_pointer = NewNode;
        cout << node_pointer << endl;
        size++;
        cout << "Pushed" << endl;

    }

    else if (size > 0)
    {
        NewNode->previous_node = node_pointer;
        node_pointer = NewNode;
        size++;
        cout << "Pushed" << endl;
    }
}

void pop() {

    if (size > 1) {

        Node* Temp_Node = node_pointer;
        cout << Temp_Node->node_value << endl;
        delete node_pointer;
        node_pointer = Temp_Node->previous_node;
        size--;
    }

    else if (size == 1) {
        Node* Temp = node_pointer;
        cout << Temp->node_value << endl;
        delete node_pointer;
        node_pointer = nullptr;
        size--;
    }

    else {
        cout << "empty" << endl;
    }

}

Также вы можете воспользоваться SmartPointer: вы не несете ответственности за «новый» и «удаление» объекта в куче.

#include <memory>
using namespace std;
class Node {
    using node_ptr = std::shared_ptr<Node>;
public:
    int node_value;
    node_ptr previous_node;
};

class Stack {
    using node_ptr = std::shared_ptr<Node>;
public:
    node_ptr node_pointer = nullptr;
    int size = 0;

void push(int number) {

    node_ptr NewNode = std::make_shared<Node>();

    NewNode->node_value = number;

    if (size == 0) {
        node_pointer = NewNode;
        cout << node_pointer << endl;
        size++;
        cout << "Pushed" << endl;
    }

    else if (size > 0)
    {
        NewNode->previous_node = node_pointer;
        node_pointer = NewNode;
        size++;
        cout << "Pushed" << endl;
    }
}

void pop() {

    if (size > 1) {

        node_ptr Temp_Node = node_pointer;
        cout << Temp_Node->node_value << endl;
        //delete node_pointer; 
        //no need to delete here, it will be automatically destructed when Temp_Node leaves this scope.
        node_pointer = Temp_Node->previous_node;
        size--;
    }

    else if (size == 1) {
        node_ptr Temp = node_pointer;
        cout << Temp->node_value << endl;
        //delete node_pointer;
        node_pointer = nullptr;
        size--;
    }

    else {
        cout << "empty" << endl;
    }

}

};

0 голосов
/ 02 июня 2018

Одна главная проблема - это две строки:

Node NewNode;
...
node_pointer = &NewNode;

Первая строка определяет локальную переменную.Затем вы сохраняете указатель на эту локальную переменную.И эта переменная выйдет из области видимости, и объект NewNode будет разрушен, когда функция завершится.Оставив вас с недопустимым указателем.

Разыменование этого недопустимого указателя приведет к неопределенному поведению .

Стандартным решением является динамическое распределение узловс new:

Node* NewNode = new Node;
...
node_pointer = NewNode;

Конечно, вы должны запомнить delete узлы, как только вы закончите с ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...