2016-11-04 76 views
0

我想写一个类设置链接列表来存储整数。编译和我的Mac的终端上运行后,这是输出:operator = on指针可能导致mac上的段错误

[] 
[10] 
[10, 20] 
Segmentation fault: 11 

但我期待看到以下的输出:

[] 
[10] 
[10, 20] 
[10, 20] 
[10, 20, 30] 

我想知道,如果它是我的操作有问题=函数,还是我不能用指针的operator =函数?如果是这样,我该如何纠正这个问题,以便程序按照我的预期输出?我真的很感激你的帮助。提前致谢!

#include <iostream> 
using namespace std; 

class Node { 
    public: 
    int value; 
    Node* next; 
    Node(int n, Node* ptr = NULL) : value(n), next(ptr) {} 
}; 

class Set { 
    Node* head; 
    friend ostream& operator<<(ostream&, const Set&); 
    public: 
    Set() : head(NULL) {} 
    Set(const Set& another){ *this = another; } 
    ~Set(); 
    Set& operator+=(const int&); 
    Set& operator=(const Set&); 
}; 

int main() { 
    int num1 = 10; 
    int num2 = 20; 
    int num3 = 30; 
    Set set1; 
    cout << set1; 
    Set* set2; 
    set1 += num1; 
    cout << set1; 
    set1 += num2; 
    cout << set1; 
    set2 = new Set(set1); 
    cout << *set2; 
    *set2 += num3; 
    cout << *set2; 
    delete set2; 
    return 0; 
} 

Set::~Set() { 
    Node* current = head; 
    while (current != NULL) { 
     Node* temp = current; 
     current = current->next; 
     delete temp; 
    } 
} 

Set& Set::operator+=(const int& aNum) { 
    if (head == NULL) { 
     head = new Node(aNum); 
     return *this; 
    } 
    Node* previous = head; 
    Node* current = head->next; 
    while (current != NULL) { 
     previous = current; 
     current = current->next; 
    } 
    previous->next = new Node(aNum); 
    return *this; 
} 

Set& Set::operator=(const Set& another) { 
    if (this != &another) { 
     Node* current = head; 
     while (current != NULL) { 
      Node* temp = current; 
      current = current->next; 
      delete temp; 
     } 
     Node* anotherCurrent = another.head; 
     while (anotherCurrent != NULL) { 
      *this += anotherCurrent->value; 
      anotherCurrent = anotherCurrent->next; 
     } 
    } 
    return *this; 
} 

ostream& operator<<(ostream& os, const Set& s) { 
    os << "["; 
    for (Node* p = s.head; p != NULL; p = p->next) { 
     os << p->value; 
     if (p->next != NULL) 
      os << ", "; 
    } 
    os << "]" << endl; 
    return os; 
} 
+4

解决此类问题的正确工具是您的调试器。在*堆栈溢出问题之前,您应该逐行执行您的代码。如需更多帮助,请阅读[如何调试小程序(由Eric Lippert撰写)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。至少,您应该\编辑您的问题,以包含一个[最小,完整和可验证](http://stackoverflow.com/help/mcve)示例,该示例再现了您的问题,以及您在调试器。 –

+0

'Set(const Set&another){* this = another; }' - 这不是编写拷贝构造函数的好方法。你应该在赋值操作符的帮助下编写拷贝构造函数(假设赋值操作不存在)。然后,一旦你这样做,写赋值操作符变成了2行函数。 – PaulMcKenzie

+0

@PaulMcKenzie thx寻求帮助。我已经重写了拷贝构造函数,而不使用赋值操作符,它工作。但是,我不知道为什么复制构造函数不能使用赋值运算符?另外,如何使用复制构造函数来编写赋值运算符?非常感谢^ – mlkw

回答

3

你必须复制之前删除以前的列表时,否则+=运营商将使用head设置headNULL,它是当前未分配,但不NULL

Set& Set::operator=(const Set& another) { 
    if (this != &another) { 
     Node* current = head; 
     while (current != NULL) { 
      Node* temp = current; 
      current = current->next; 
      delete temp; 
     } 
     head = NULL; // <============== code to add 
     Node* anotherCurrent = another.head; 
     while (anotherCurrent != NULL) { 
      *this += anotherCurrent->value; 
      anotherCurrent = anotherCurrent->next; 
     } 
    } 
    return *this; 

BTW一个很有趣设计模式,必须阅读:copy-and-swap idiom

+0

非常感谢您的帮助。我添加了代码行,但问题仍然存在。然而,重写复制构造函数而不使用赋值操作符的做法,尽管我不知道为什么。无论如何,我一定会阅读你提供的链接xd – mlkw

+0

@mlkw - 阅读我的评论给你。一旦您更改了复制构造函数(全部归因于使用复制/交换习语),赋值运算符就变成了3行函数。 – PaulMcKenzie