2016-11-04 77 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