1

ですから、なぜこれが起こっているのか、私は本当にイライラしています。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;
}
4

1 に答える 1

2

代入演算子には根本的に間違っていることが 2 つあります。

  • すべての制御パスが値を返すわけではありません。
  • そもそも一時的な最終コピーは必要ありません。関数は、具体的には参照を返す必要があります*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 に設定されます (作成時にリストを適切に終了したと仮定すると、そのように見えます)。

于 2013-10-18T04:45:20.457 に答える