我想实现循环双链表。此列表只包含传入的字符串对象中的这些字符 这是我的代码,但我总是遇到seg错误。我在这个列表中使用了一个虚拟头
#ifndef MY_LIST_H
#define MY_LIST_H
#include <string>
#include <iostream>
using namespace std;
/**------ -----------------
* dummy |->|pred|value|next|
* ------ -----------------
* */
struct Node
{
char value;
Node *next;
Node *pred;
Node( char value): value(value), next(0), pred(0){};
};
class MyList
{
private:
Node* head;
unsigned int count; // count number of node
public:
// default constructor
MyList(): count(0)
{
head = new Node('P');
}
//Constructs a list from a passed-in string object,
MyList(const string& str): count(0)
{
Node *cur = head;
if(count == 0)
{
head-> pred = head;
head-> next = head;
}
else
{
for( unsigned i =0; i< str.length(); ++i)
{
cur->next = new Node(str.at(i));
Node *temp = cur->next;
temp-> pred = cur;
++count;
if(count == str.length())
{
cur->next->next = head;
head-> pred = cur-> next->pred;
}
}
}
}
void print() const
{
Node *cur = head->next;
while( cur != head)
{
cout << cur-> value;
cur = cur-> next;
}
}
};
#endif
答案 0 :(得分:1)
你似乎没有很好地理解构造函数。
初始化类时,只调用一个构造函数。如果需要,可以从另一个构造函数中调用构造函数,但这不是defaut:Can I call a constructor from another constructor (do constructor chaining) in C++?。
在您的实例中,您的第二个构造函数应该是这样的:MyList(const string& str): MyList() { ... }
这样head
可以正确地进行初始化,并且您不会创建段错误。
另外,您可以在调试模式下以调试模式运行代码,并找出代码崩溃的行。标题中的using namespace ...;
也是不好的做法,因为你不知道你的标题会被包含在哪里。
答案 1 :(得分:0)
如果没有看到你如何使用这些类,但是你的MyList构造函数在字符串上重载会立刻被打破,很难确切地说出发生了什么。它将计数设置为0
,因此您知道它将始终输入if
子句而不是else
。
MyList(const string& str): count(0)
{
Node *cur = head;
if(count == 0)
{
head-> pred = head;
head-> next = head;
}
else . . .
head
。你确实在默认的构造函数中设置它,但是它似乎也没有做任何其他事情。
构造函数的目的是从头开始构造一个有效的对象。有时一个构造函数重载可能委托给另一个,以避免重复代码,但我不确定你在这里尝试做什么。
假设第二个构造函数实际上是一个辅助方法,那么它仍然无法工作,因为计数永远不会超过零(除了else
子句,但你无法到达那里与count==0
)。
我承认我看起来并不是很认真,但我猜测如果执行到目前为止:
cur->next->next
当您尝试访问它时,并不总是设置。如果cur-&gt; next是nullptr,那么你的程序就会死掉。