2

我有一个非常简单的课程。它有一个指针成员变量。我想重载 + 运算符。但是,它不起作用!这是我的代码:

#include <iostream>
using namespace std;


template <typename T> 
struct Node{
    Node *next;
    T data;
};

template <typename T> 
class stack{
protected:
    Node <T> *head;

public:
    stack();
    ~stack();
    bool push(T);
    stack <T> operator+ (stack <T>);

};

template <typename T> 
stack<T>::stack(){
    head = NULL;
}

template <typename T>  
stack <T>::~stack(){
    Node <T> *temp;

    while(head){
        temp = head;
        head = head->next;
        delete temp;
    }
}

template <typename T> 
bool stack <T>::push(T data){
    Node <T> *newElem = new Node <T>;
    if (!newElem) return false;

    newElem->next = head;
    newElem->data = data;
    head = newElem;
    return true;
}

template <typename T> 
stack <T> stack<T>::operator+ (stack <T> stack1){
    stack <T> result;
    Node <T> *temp = head;

    while (temp) {
        result.push(temp->data);
        temp = temp->next;
    }

    temp = stack1.head;
    while (temp) {
        result.push(temp->data);
        temp = temp->next;
    }

    return result;
}

int main(){
    stack <int> myStack1, myStack2, myStack3;

    myStack1.push (1);
    myStack1.push (2);

    myStack2.push (3);
    myStack2.push (4);

    myStack3 = myStack1 + myStack2; //  here at runtime myStack3 is not the result of myStack1 + myStack2. 
    return 0;
}

你能帮我解决这个问题吗?请注意,这只是为了练习。

非常感谢。

4

2 回答 2

2

您在类声明中声明了其他内容,+=而不是+在定义中编写:

stack <T> operator+ (stack <T>);
                  ^

stack <T> stack<T>::operator+= (stack <T> stack1){
                            ^^
于 2013-10-12T08:09:13.367 回答
2

您的问题是您正在创建运算符右侧的副本。签名应该是:

template <typename T> 
stack <T> stack<T>::operator+ (const stack <T>& stack1) { ... }

所以你只是引用stack1,而不是复制它。

这将解决您遇到的直接问题,但从长远来看,您还希望实现一个正确的复制构造函数,因为 a 的所有副本stack当前都会破坏内存,因为它们链接相同的元素并且析构函数将删除它们,另一个stack然后仍然引用已删除的元素

这就是为什么您看到“结果”具有预期值的原因,调用的副本stack1尚未被删除。但是当operator+返回时,它会删除stack1,因此所有元素都会stack1被删除。并非所有复制到引用元素的结果的指针stack1都是无效的。这就是为什么stack3通话后出现断线的原因。

另请参阅三规则,阅读答案中的“管理资源”部分。


更新:这还不够,因为您还分配了 的结果operator+,再次适用三规则,因为您也没有正确的分配运算符。您可能希望将这些添加到您的课程中:

template <typename T> 
stack<T>::stack(const stack<T>& src)
{
    // this will reverse the src, I'll leave it to you to fix the order!
    head = NULL;
    Node<T>* tmp = src->head;
    while( tmp ) {
        push( tmp->data );
        tmp = tmp->next;
    }
}

template <typename T> 
stack<T>& stack<T>::operator=( stack<T> src ) // copy the argument is OK here!
{
    stack old;
    old->head = head;
    head = src->head;
    src->head = NULL;
}

由于您正在学习,因此以上是一个很好的起点。你现在必须

  • 以不颠倒元素顺序的方式实现复制构造函数
  • 了解赋值运算符的工作原理。我使用了一个不寻常的实现,但是一旦你理解了它,你就会学到很多关于对象生命周期的知识:)
于 2013-10-12T08:37:25.390 回答