2016-04-20 8 views
-3

Я реализую двусвязный список, и я получаю segfault, когда пытаюсь получить доступ к члену, который действительно принадлежит объекту, на который указывает указатель на член. Мой связанный список состоит из узлов, которые имеют значение и следующий и предыдущий указательВыделение элемента указателя

Строка (Это реализация голых костей из предыдущего проекта):

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 (я знаю, что это Безразлично» т реализовать «большой тройки», я предпочел бы сохранить этот класс как минимум):

#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; 
     } 
    }; 

двусвязному список:

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; 
} 

Любая помощь приветствуется!

+0

Что именно вы спрашиваете? и можете ли вы опубликовать только код, о котором идет речь? –

+3

Реализация «большого дерева» не является приятным, но обязательным в вашем случае. – SergeyA

ответ

2

Node (я знаю, что это не реализует «большой тройки», я предпочел бы сохранить этот класс до минимума):

Следует отметить, что копировать/перемещать конструкторы и операторы присваивания все еще предоставляются как compiler generated default versions.

Чтобы избежать этого, в тех случаях, вы не хотите, чтобы реализовать big three (or five) вам нужно явно delete их:

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; 
    } 
}; 

 Смежные вопросы

  • Нет связанных вопросов^_^