这是一个使用链表实现堆栈的非常简单的程序。 请帮助我找出导致程序崩溃的逻辑错误。
class LLStack {
public:
struct Node {
int data;
Node* next;
Node(int n) {
data = n;
next = 0;
}
Node(int n, Node* node) {
data = n;
next = node;
}
};
LLStack();
LLStack(const LLStack&);
LLStack& operator = (const LLStack&);
~LLStack();
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
Node* head;
};
LLStack::LLStack() {
head = 0;
}
LLStack::LLStack(const LLStack& s) {
head = new Node(NULL);
head->data = s.head->data;
head->next = new Node(*(s.head->next));
}
LLStack::~LLStack() {
this->flush();
}
LLStack& LLStack::operator = (const LLStack& s) {
this->head = new Node(NULL);
this->head->data = s.head->data;
this->head->next = new Node(*(s.head->next));
return *this;
}
void LLStack::push(int x) {
if (head == 0) head = new Node(x);
else {
Node* temp = new Node(x, head);
head = temp;
}
}
int LLStack::pop() {
if (head == 0) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
else {
Node* temp = head;
int n = temp->data;
head = temp->next;
delete temp;
return n;
}
}
int LLStack::top() {
if (head == 0) {
cout << "\n\nNo elements in the stack\n\n";
return -1;
}
else {
return head->data;
}
}
bool LLStack::isEmpty() {
return (head == 0);
}
void LLStack::flush() {
if (head == 0) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
Node* temp = 0;
while (head != 0) {
temp = head;
cout << temp->data << " ";
head = head->next;
delete temp;
}
cout << endl << endl;
}
这是麻烦制造者的功能:
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
int main() {
LLStack s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.push(5);
reverseStack(s);
cout << "\n\nFlushing s:\n";
s.flush();
system("pause");
return 0;
}
我已经实现了自己的复制构造函数和复制赋值运算符。我不明白为什么它会在跑步时崩溃。在刷新时,它会在崩溃前显示垃圾值。
答案 0 :(得分:0)
问题在于您的复制赋值运算符。考虑:
void reverseStack(LLStack& s1) {
LLStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
}
一切正常,直到你从函数返回,此时调用s2
的析构函数。析构函数调用flush()
,删除s2
的所有堆栈元素。在您的复制赋值运算符(以及复制构造函数)中,您创建了两个节点:head
和head->next
;其余节点在两个堆栈之间共享,因此在删除s2
后,s1.head->next->next
指向已删除的节点,但您仍尝试访问它。
解决方案是让复制赋值运算符(和复制构造函数)创建堆栈的正确深层副本,而不仅仅是前两个元素,这样(也负责自我赋值):
LLStack& LLStack::operator=(const LLStack& s) {
if (this==&s) return *this; // self assignment
flush(); // avoid memory leak
head = new Node(*s.head);
Node* s_ptr = s.head;
Node* t_ptr = head;
while (s_ptr->next) {
t_ptr->next = new Node(*s_ptr->next);
s_ptr = s_ptr->next;
t_ptr = t_ptr->next;
}
return *this;
}
请记住,复制构造函数也应该这样做。