2016-04-20 17 views
-3

Ich bin eine doppelt verknüpfte Liste implementieren und ich erhalte einen segfault, wenn ich versuche, auf ein Mitglied eines Objekts, auf das von einem Member-Zeiger verwiesen wird, zuzugreifen. Meine verknüpften Liste besteht aus Knoten zusammengesetzt ist, die einen Wert haben und einen nächsten und vorherigen ZeigerDereferenzieren eines Members Zeiger

String (Dies ist die nackten Knochen Umsetzung von einem früheren Projekt):

class String{ 
    public: 
    int len; 
    char *str; 

    String() 
    :len(0), str(nullptr){} 

    String(char const* S) 
    :len(strlen(S)), str(new char[len +1]){ 
     assert(S != 0); 
     strcpy(str, S); 
    } 

    ~String(){ 
     delete[]str; 
    } 
}; 

Node (Ich weiß, das ‚doesn t implementieren 'die großen drei', würde ich eher diese Klasse auf ein Minimum):

#include <initializer_list> 

    template<typename T> 
    struct Node{ 
     T value; 
     Node* next; 
     Node* prev; 

     Node() = default; 
     Node(T t, Node* n, Node* p) 
     :value(t), next(n), prev(p){} 

     Node & operator=(const Node & N){ 
     value = N.value; 
     next = N.next; 
     prev = N.prev; 
     return *this; 
     } 
    }; 

doppelt verketteten Liste:

template<typename T> 
struct List 
{ 
    List(std::initializer_list<T>); 
    Node<T>* head; 
    Node<T>* tail; 
    List() 
    :head(nullptr), tail(nullptr){} 

    //copy constructor 
    List(const List<T> & l){ 
    Node<T>* p = l.head; 
    head = p; 
    Node<T>* past; 
    while(p){ 
     Node<T>* q = new Node<T>; 
     *q = *p; 
     if(head == p){ 
     head = q; 
     }else{ 
     past->next = q; 
     q->prev = past; 
     } 
     past = q; 
     p = q->next; 
    } 
    tail = past; 
    } 


    //copy assignment 
    List & operator=(const List & L){ 
    List temp = L; 
    swap (*this, temp); 
    return *this; 
    } 

    Node<T>* getHead()const{ 
    return head; 
    } 

    Node<T>* getTail()const{ 
    return tail; 
    } 

    void swap(List a, List b){ 
    Node<T>* temp1 = a.getHead(); 
    Node<T>* temp2 = a.getTail(); 

    a.head = b.getHead(); 
    a.tail = b.tail; 
    b.head = temp1; 
    b.tail = temp2; 
    } 

    void push_back(T t){ 
    Node<T>* p = new Node<T>(t, nullptr, tail); 
    if(tail){ 
     tail->next = p; //Segfault occurs here 
    }else{ 
     head = p; 
    } 
    tail = p; 
    } 

    int compare(const List<T> & b)const{ 
    Node<T>* temp1 = this->head; 
    Node<T>* temp2 = b.head; 
    while (temp1 != this->tail && temp2 != b.tail) { 
     if (temp1->value < temp2->value) 
     return -1; 
     if (temp2->value < temp1->value) 
     return 1; 
    } 
    if (temp1 == this->tail) { 
     if (temp2 != this->tail) 
     return -1; // [first1, last1) is a prefix of [first2, last2) 
     else 
     return 0; // [first1, last1) and [first2, last2) are equivalent 
    } 
    else { 
     return 1; // [first2, last1) is a prefix of [first1, last1) 
    } 
    } 

    size_t size()const{ 
    size_t n = 0; 
    Node<T> *p = head; 
    while (p){ 
     ++n; 
     p = p->next; 
    } 
    return n; 
    } 

    void clear(){ 
    Node<T> *p = head; 
    while(p){ 
     Node<T>* q = p-> next; 
     delete[] p; 
     p = q; 
    } 
    head = tail = nullptr; 
    } 

    ~List<T>(){ 
    clear(); 
    } 
}; 

template<typename T> 
List<T>::List(std::initializer_list<T> list) 
{ 
    for (T const& elem : list) 
    push_back(elem); 
} 

Main:

int main() 
{ 
    List<String> v1 = {"a", "b", "c"}; //segfault occurs on second pass of initialization loop 
    return 0; 
} 

Jede Hilfe ist willkommen!

+0

Was genau fragen Sie? und könnten Sie nur den fraglichen Code posten? –

+3

Das Implementieren des "großen Baums" ist nicht nett, aber in Ihrem Fall ein Muss. – SergeyA

Antwort

2

Node (Ich weiß, das ‚die großen Drei‘ nicht implementiert, würde ich lieber diese Klasse auf ein Minimum):

Sie sollten beachten, dass die kopieren/verschieben und Zuweisungsoperator werden immer noch als compiler generated default versions bereitgestellt.

Um zu vermeiden, dass in Fällen Sie die big three (or five) nicht implementieren möchten Sie ausdrücklich delete sie benötigen, um:

class String{ 
    public: 
    int len; 
    char *str; 

    String() 
    :len(0), str(nullptr){} 

    String(char const* S) 
    :len(strlen(S)), str(new char[len +1]){ 
     assert(S != 0); 
     strcpy(str, S); 
    } 

    // Add these: 
    String(const String&) = delete; 
    String(String&&) = delete; 
    String& operator=(const String&) = delete; 
    String& operator=(String&&) = delete; 

    ~String(){ 
     delete[]str; 
    } 
};