C ++堆栈实现pop函数不起作用

时间:2017-01-26 01:59:40

标签: c++ stack

我正在实现一个包含链表的堆栈以供审核。我的弹出功能无法正常工作。我创建了一个测试,主要的节点做了我的linkedList函数正在做的完全相同的事情,但我随时都会遇到分段错误。这是代码。

#include <iostream>

struct Node{
  int data;
  Node* next;
};

class Stack{
  private:
    Node head;
    int size;
  public:
    Stack();
    ~Stack();
    int getSize();
    void push(int val);
    int pop();
    void printStack();
};

Stack::Stack(){
  head.data = 0;
  head.next = NULL;
}

Stack::~Stack(){
}

int Stack::getSize(){
  return size;
}

void Stack::push(int val){
  Node newNode;
  newNode.data = val;
  if(size == 0) newNode.next = NULL;
  else newNode.next = head.next;
  head.next = &newNode;
  size++;
}

int Stack::pop(){
  int returnVal = head.next->data;
  head.next = head.next->next;
  return returnVal;
}
}


int main(){
  Stack s;
  s.push(8);
  s.push(30);
  s.push(40);
  int value = s.pop();
  int value2 = s.pop(); //segmentation fault
  std::cout<<value<<"\n"<<value2<<"\n"; 


/* This works correctly
  Node head;
  head.data = 0;
  head.next = NULL;
  Node n1;
  n1.data = 5;
  n1.next = NULL;
  head.next = &n1;
  Node n2;
  n2.data = 8;
  n2.next = head.next;
  head.next = &n2;
  Node n3;
  n3.data = 30;
  n3.next = head.next;
  head.next = &n3;

  int value = head.next->data;
  std::cout << value << "\n";
  head.next = head.next->next;
  value = head.next->data;
  std::cout << value << "\n";
*/
  return 1;
}

4 个答案:

答案 0 :(得分:2)

void Stack::push(int val){
  Node newNode;

newNode被声明为push()函数自动范围内的本地对象。

这意味着当push()返回时,此对象将自动销毁。这是&#34;自动范围&#34;装置

push()中的代码尝试将此对象插入到堆栈中,并假定在push()返回后该对象将存在。当然,这不是真的,这最终会破坏内存,导致不确定的行为。

从根本上说,这不是对象生命周期和范围在C ++中的工作原理。

答案 1 :(得分:1)

问题是如何创建节点。在您的情况下,您创建一个局部变量,它只存在于函数push()的范围内。你可以使用这样的东西。

void Stack::push(int val){
  Node* newNode = new Node;
  newNode->data = val;
  /* ... */ 
}

编辑:添加了一个版本的堆栈(完全没有完成)

#include <iostream>

struct Node{
  int data;
  Node* next;
};

class Stack {
  private:
    Node* head;
    int size;

  public:
    Stack();
    ~Stack();
    int getSize();
    void push(int val);
    int pop();
    void printStack();
};

Stack::Stack() : head(0), size(0)
{
}

Stack::~Stack(){
}

int Stack::getSize(){
  return size;
}

void Stack::push(int val){
  Node* newNode = new Node;
  newNode->data = val;
  newNode->next = head;

  head = newNode;
  size++;
}

int Stack::pop(){
    if(head != 0)
    {
        int val = head->data;

        Node* tmp = head;
        head = head->next;

        tmp->next = NULL;
        delete tmp;

        size--;

        return val;
    }
    else
    {
        return -1; // what happens if stack is empty ?      
    }
}

答案 2 :(得分:1)

我认为您的push()pop()方法都存在问题。您可以尝试使用这些版本:

// create new node, point it to current head, and then assign it as new head
void Stack::push(int val){
    Node* newNode = new Node;
    newNode->data = val;
    newNode->next = head;             // OK even if head == NULL
    head = newNode;
    size++;
}

// retrieve value from head (if it exists), pop the head and return the value
int Stack::pop(){
    if (head == NULL) return -1;     // -1 indicates empty stack
    int returnVal = head->data;      // get popped value
    Node* temp = &head;
    head = head->next;               // pop the top of the stack
    delete temp;
    size--;
    return returnVal;
}

答案 3 :(得分:0)

您的push代码存在问题,实际上是:

void Stack::push(int val){
  Node newNode;
  newNode.data = val;
  if(size == 0) newNode.next = NULL;
  else newNode.next = head.next;
  head.next = &newNode;
  size++;
}

写作时

Node newNode;

您使用自动存储持续时间声明Node对象(您有时会听到这个名为“在堆栈上”)。仅当Node函数正在运行时,此push才存在,并且只要函数返回,节点就不再存在。稍后尝试使用该节点会导致未定义的行为,实际上可能是从彻底崩溃到回读垃圾数据的任何行为。

要解决此问题,您需要使用动态分配。使用new Node创建节点并存储指向它的指针。以这种方式创建的对象会直播,直到明确地销毁它们,这意味着它们将在push调用完成后生存。然后,您需要调整pop以释放内存。