提问人:Jonathan Chiou 提问时间:2/8/2014 最后编辑:Jonathan Chiou 更新时间:2/8/2014 访问量:5517
链表赋值运算符
Linked list assignment operator
问:
我为链表的重载 = 运算符编写了一些代码,但由于某种原因它没有做任何事情,我无法弄清楚为什么。
包含链表的类称为 String,结构 ListNode 是节点本身。
列表节点:
struct ListNode
{
char info;
ListNode * next;
ListNode(char newInfo, ListNode * newNext)
: info( newInfo ), next( newNext )
{
}
};
字符串:
class String {
private:
ListNode* head;
public:
String( const char * s = "");
String( const String & s );
String operator = ( const String & s );
~String();
}
ostream & operator << ( ostream & out, String& str );
istream & operator >> ( istream & in, String & str );
字符串 .cpp:
String::String( const char * s) {
if (s == "") {
head = NULL;
return;
}
ListNode* newNode = new ListNode(s[0], NULL);
head = newNode;
ListNode* current = head;
for (int i = 1; s[i] != 0; current = current->next) {
current->next = new ListNode(s[i], NULL);
++i;
}
}
String::String(const String& s ) {
ListNode* current = new ListNode((s.head)->info, NULL); //make all next's null just in case
head = current;
for(ListNode* sstart = s.head->next; sstart != NULL; sstart = sstart->next) {
current->next = new ListNode(sstart->info, NULL);
current = current->next;
}
}
//RETURN STRING BY REFERENCE OR COPY CONSTRUCTOR IS CALLED
String& String::operator = ( const String & s ) {
ListNode* start = head;
ListNode* tmp;
while(start != NULL) {
tmp = start->next;
delete start;
start = tmp;
}
head = NULL;
if (s.head == NULL)
return *this;
ListNode* current = new ListNode((s.head)->info, NULL); //make all next's null just in case
head = current;
for(ListNode* sstart = s.head->next; sstart != NULL; sstart = sstart->next) {
current->next = new ListNode(sstart->info, NULL);
current = current->next;
}
return *this;
}
String::~String() {
ListNode* nextNode = head;
ListNode* tmp;
while(nextNode) {
tmp = nextNode->next;
delete nextNode;
nextNode = tmp;
}
}
ostream & operator << ( ostream & out, String& str) {
for (int i = 0; i < str.length(); ++i) {
out << str[i];
}
return out;
}
istream & operator >> ( istream & in, String & str ) {
int len = in.gcount();
char* buf = new char[len];
char inChar;
for(int i = 0; in >> inChar; ++i) {
buf[i] = inChar;
}
String tmp(buf);
str = tmp;
}
在第一个循环中,我删除了按头指向的链表。在那之后,我将 head 设置为 NULL 以表示 s 根本不包含任何内容的情况。如果不是,那么,我将 current 设置为 s 中第一个 ListNode 的副本,并将 current 存储在 head 中(如果我使用 head 遍历,那么我将丢失指向列表开头的指针)。最后,我的第 2 个循环将把 s 的其余部分“附加”到电流上。
当我运行代码时,什么也没发生。我的终端会打印出一行空白,然后什么都没有,向我暗示我可能在某个地方无限。我的代码有什么问题?
编辑:更改了此链表的删除,问题仍然存在。
答:
4赞
jerry
2/8/2014
#1
通过访问此代码片段中已删除的对象(自 tmp == start 起),您会导致未定义的行为:
tmp = start;
delete start;
start = tmp->next;
可能还有其他问题,但首先要解决这个问题。例如,您可以在删除以下内容之前将下一个指针存储在临时变量中:
tmp = start->next;
delete start;
start = tmp;
评论
0赞
Jonathan Chiou
2/8/2014
改变了这一点,我仍然有同样的问题。这一次,我相当确定这是因为我在某个地方搞砸了我的第二个 for 循环。编辑:我使用的示例是:String s(“Hello”);字符串 t(“再见”);s = t;
0赞
jerry
2/8/2014
@JonathanChiou 几点:我们不知道你是如何实现构造函数的,你没有在该代码段中包含任何输出语句,我们不知道类是如何写出自己的,请编辑你的问题并将额外的代码放在那里。String( const char *)
0赞
jerry
2/9/2014
@JonathanChiou 请阅读 stackoverflow.com/help/mcve sscce.org,然后给我们一个有用的例子。更新后的代码更完整,但仍缺少一些内容,并且包含一些语法错误。修复这些问题后,我刷掉了代码,类似于我猜想你已经做到了。结果确实打印出了我所期望的。顺便说一句,至少有一个不相关的语义错误(不要检查构造函数中的空字符串char *
s==""
)
1赞
michaeltang
2/8/2014
#2
我测试了你在问题中输入的代码,似乎是<<重载的问题 希望会有所帮助
ostream & operator << ( ostream & out, String& str) {
ListNode *p = str.head; // change head to public or define a public function get_head;
while(p)
{
out << p->info;
p = p->next;
}
return out;
}
评论
0赞
Jonathan Chiou
2/8/2014
我确实有一个复制构造函数,但我认为它与我的问题无关。
0赞
michaeltang
2/8/2014
@JonathanChiou,你把所有的代码都放在问题中方便吗?
0赞
PaulMcKenzie
2/8/2014
如果你写了一个复制构造函数,那么为什么不让你的赋值运算符使用复制/交换习惯用法调用复制构造函数呢?否则,您只是在复制代码。
0赞
PaulMcKenzie
2/8/2014
假设您确实编写了一个复制构造函数并对其进行了彻底测试,以下是描述的复制/交换习语:stackoverflow.com/questions/3279543/...使用此惯用语,您不再需要在赋值运算符中编写所有这些代码。
评论
new
delete