【问题标题】:Linked List overload operator = Run time error链表重载运算符 = 运行时错误
【发布时间】:2013-10-18 04:10:19
【问题描述】:

所以我对为什么会发生这种情况感到非常沮丧。我正在实现一个类似于 std::string 的类,但这是使用链接列表而不是数组。我的重载运算符 = 出于某种奇怪的原因无法正常工作。下面你可以看到,当我在方法内打印指针时,字符串被复制到链接列表中,但是当我用这个指针创建一个要返回的字符串对象时,控制台会打印出无限的垃圾。我在这里缺少什么的任何想法? (我只是贴相关代码)

static int NumAllocations = 0;

struct ListNode {
    char info;
    ListNode *next;
    ListNode () : info('0'), next(0) {}
    ListNode ( char c ) : info (c), next(0) {}


};


class MyString {
 private:
    ListNode *head;
    static void delstring (ListNode *l);
    static int strlen (ListNode * head);
    static ListNode* strcpy (ListNode *dest, ListNode *src);
 public:

MyString::MyString () : head(0) {}

MyString::MyString (ListNode *l) : head(l) {}

MyString::MyString( const MyString & s ) {
    if (s.head == 0)
        head = 0;
    else
        head = strcpy(head, s.head);
}


MyString MyString::operator = (const MyString & s ){               
    ListNode *renew = NULL;
    if (head != s.head) {
        if (head != 0)
            delstring(this -> head);

        head = strcpy(head, s.head);
        // printList(head); (this prints out the string just fine, so it must be the                                   constructor ? but what about it ?!

        MyString res (head);
        return res;
    }
}


MyString::~MyString(){
    if (head == 0)
        return;
    ListNode *temp = NULL;
    do {
        temp = head -> next;
        delete head;
        -- NumAllocations;
        head = temp;
    } while (temp != 0);
}

静态公共函数

ListNode* MyString::strcpy (ListNode *dest, ListNode *src){
    dest = new ListNode (src -> info);
    ++ NumAllocations;
    ListNode *iter = dest;
    for (ListNode *ptr = src -> next; ptr != 0; ptr = ptr ->next){
        iter -> next = new ListNode (ptr -> info);
        iter = iter -> next;
        ++ NumAllocations;
    }
    return dest;
}


void MyString::delstring (ListNode *l){
    if (l == 0)
        return;
    ListNode *temp = NULL;
    do {
        temp = l -> next;
        delete []l;

        -- NumAllocations;
        l = temp;
    } while (temp != 0);
    l = 0;
}

【问题讨论】:

  • 类定义将很好地帮助这项工作。节点管理代码更是如此。我看到了为什么dest 甚至提供 给命名不佳的strcpy 成员的零原因。它是按值传递的,无论它是什么都立即在第一行丢失,所以它也可能是一个局部变量而不是一个参数。该功能看起来可能有问题,所以我将从那里开始。
  • 我添加了类定义。 strcpy 是 std::string 的成员函数,并且此类要尽可能与该类相同,因此名称选择。就像我提到的列表已正确复制,因为当我在返回之前打印它时,它打印得很好,当我尝试在 operator = 方法的最后两行中使用该指针“head”创建一个新对象时它会搞砸。

标签: c++ pointers constructor linked-list


【解决方案1】:

您的赋值运算符有两点根本错误。

  • 并非所有控制路径都返回值。
  • 首先,您不应该需要临时最终副本。该函数应该返回一个引用,特别是*this

所以...

MyString& MyString::operator = (const MyString & s )
{               
    if (head != s.head) 
    {
        if (head != 0)
            delstring(this -> head);
        head = strcpy(head, s.head);
    }
    return *this;
}

此外,我在这段代码中看到的所有内容都表明 ListNode 对象是单独分配并链接在一起的,但在 delstring 成员中您可以这样做:

void MyString::delstring (ListNode *l)
{
    if (l == 0)
        return;
    ListNode *temp = NULL;
    do {
        temp = l -> next;
        delete []l;  // <<==== vector delete of single allocated item

        -- NumAllocations;
        l = temp;
    } while (temp != 0);
    l = 0;
}

不妨试试这个:

void MyString::delstring (ListNode *& l)
{
    while (l)
    {
        ListNode *temp = l;
        l = l->next;
        delete temp;
        --NumAllocations;
    }
}

注意这需要一个指针引用而不是一个指针。一旦列表为空,它会将调用者的指针设置为 nullptr(假设您在构造时正确终止了列表,并且看起来像您这样做)。

【讨论】:

  • 非常感谢您的帮助,很抱歉我没有包含更多代码,不想让问题过于复杂,但我想我让事情变得更糟了。我确实编写了一个复制构造函数,它现在包括析构函数。我可以清楚地看到你的观点。我会尝试看看这是否会改变任何事情。 (但我怀疑析构函数做错了什么,因为在此方法中打印对象(print(objhead))会打印字符串,但主要是不同的故事。
  • @WhosCraig 你是个了不起的人,上面的功能很完美。我仍然不明白为什么构建一个新对象会搞砸它,但这显然是错误的。非常感谢您阅读所有这些乱七八糟的代码!
  • @Tangleman 还有另一个问题,很可能是相关的;节点分配的向量破坏不当。我把它扔进去,然后交给你。
  • @WhosCraig 哈哈好吧,如果你只是指出它并试图弄清楚它,但到目前为止一切正常,我还有更多方法要做,例如重载 +=、+、>>、以及诸如查找之类的东西。
  • @WhosCraig 哦,好吧,我不小心把“[]”放在 head 之前,这意味着删除 head,就像析构函数一样,我也会修复它。再一次感谢你的帮助!希望剩下的都是小菜一碟。
猜你喜欢
  • 1970-01-01
  • 2012-07-23
  • 2012-03-23
  • 2013-11-14
  • 2016-10-18
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
相关资源
最近更新 更多