取消引用成员指针

时间:2016-04-20 17:25:47

标签: c++ doubly-linked-list member-variables member-pointers

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

String(这是以前项目的基本实现):

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

感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

  

节点(我知道这并没有实现&#39;三巨头&#39;,我宁愿将这个课程保持在最低限度):

您应该注意,复制/移动构造函数和赋值运算符仍然以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;
    }
};