-3

我正在实现一个双向链表,当我尝试访问由成员指针指向的对象的成员名时,我遇到了段错误。我的链表由节点组成,节点有一个值和一个下一个和上一个指针

字符串(这是上一个项目的基本实现):

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

节点(我知道这并没有实现“三巨头”,我宁愿把这个类保持在最低限度):

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

主要的:

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

任何帮助表示赞赏!

4

1 回答 1

2

节点(我知道这并没有实现“三巨头”,我宁愿把这个类保持在最低限度):

您应该注意,复制/移动构造函数和赋值运算符仍然作为编译器生成的默认版本提供。

为避免在您不想实现三大(或五个)的情况下发生这种情况,您需要明确说明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;
    }
};
于 2016-04-20T17:39:41.777 回答