指针未正确传递对象

时间:2018-06-02 00:49:39

标签: c++ visual-c++

我试图用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中,当我通过derefencing指针创建一个新节点时,它会回吐完全不同的实例变量。

2 个答案:

答案 0 :(得分:4)

一个主要的问题是这两行:

Node NewNode;
...
node_pointer = &NewNode;

第一行定义 本地 变量。然后保存指向该局部变量的指针。并且该变量将超出范围,并且在函数结束时将破坏对象NewNode。给你一个无效的指针。

取消引用该无效指针将导致undefined behavior

标准解决方案是使用new动态分配节点:

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

当然,一旦你完成了节点,就必须记住delete节点。

答案 1 :(得分:1)

问题来自函数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;
    }

}

};