手写链表是segfaulting,我不明白为什么

时间:2010-03-11 21:00:53

标签: c++ class linked-list

您好我正在努力工作,制作一个从c ++中运行gnuplot的界面,并且由于某种原因我的链接列表实现失败。

以下代码在plots->append(&plot)行上失败。单步执行代码,我发现由于某种原因,构造函数~John()之后会立即调用析构函数John(),而我似乎无法弄清楚原因。

下面的代码是仅在Plot*上运行的精简版本。最初我将链表作为模板类。它在ll<int>ll<char*>下工作正常但由于某种原因它以ll<Plot*>失败。

请你帮我弄清楚它失败的原因?也许可以帮助我了解如何使其发挥作用?

提前:感谢一堆!

// B2S

#include <string.h>

class Plot{
  char title[80];
public:
  Plot(){  }
};

class Link{
  Plot* element;
  Link* next;
  Link* prev;
  friend class ll;
};

class ll{
  Link* head;
  Link* tail;
public:
  ll(){
    head = tail = new Link();
    head->prev = tail->prev = head->next = tail->next = head;
  }
  ~ll(){
    while (head!=tail){
      tail = tail->prev;
      delete tail->next;
    }
    delete head;
  }
  void append(Plot* element){
    tail->element = element;
    tail->next = new Link();
    tail->next->prev = tail;
    tail->next = tail;
  }
};

class John{
  ll* plots;
public:
  John(){
   plots= new ll();
  }
  ~John(){
    delete plots;
  }
  John(Plot* plot){
    John();
    plots->append(plot);
  }
};   

int main(){
  Plot p;
  John k(&p);
}

4 个答案:

答案 0 :(得分:2)

声明:

 John();

只需构建一个新的无名John,它会被创建并立即销毁。没有办法(在当前版本的C ++中)从另一个构造函数或已经构造的对象调用构造函数。

这意味着您plots John成员的k成员永远不会被初始化,因此当您从append构造函数中调用John时崩溃

[正如Neil Butterworth评论的那样,如果您实际构建了一个ll实例,那么还有其他问题,这只是最直接的问题。]

答案 1 :(得分:2)

因为您无法在C ++中调用类似的替代构造函数。在...

John(Plot* plot){
  John();
  plots->append(plot);
}

您的第一行使用默认构造函数构造一个新的John对象,然后抛弃结果。然后它会在append上调用plots(由于它尚未设置为任何内容,因此是垃圾邮件)。将实际的plots初始化代码重构为私有方法,然后在执行任何其他操作之前在两个构造函数中调用此init方法。

答案 2 :(得分:1)

head = tail = new Link();

这里指定head和tail指向同一个链接对象。由于您从未重新分配其中任何一个,这意味着每当您更改head的任何属性(例如head.next = foo)时,都会对尾部应用相同的更改。

意思是头部和尾部将始终具有相同的元素,前身和相同的后继者。显然这不会导致预期的结果。

答案 3 :(得分:0)

  Plot p;
  John k(&p);

请改用:

  Plot * p = (Plot*) new Plot;
  John k(p);

这段代码坏了,因为一旦p超出范围,k对它的引用就会消失。这不是导致段错误的错误,但是一旦修复了其他错误,它可能会在以后导致段错误。

您需要稍后删除。