簡體   English   中英

為什么這個賦值運算符不返回復制的 object?

[英]Why doesn't this assignment operator return a copied object?

我有一個名為 Stack 的 class。 我已經實現了復制構造函數,但是對於復制賦值構造函數,我只是讓它調用復制構造函數,因為邏輯是相同的。 但由於某種原因,它只返回一個默認構造的 object。 我不明白為什么。

復制構造函數:

Stack::Stack( const Stack& s )
{
    if ( s.Empty() )
    {
        this->entry = nullptr;
    }
    else
    {
        this->entry = new Entry();
        Entry* i = this->entry;
        for ( Entry* p = s.entry; p != nullptr; p = p->next )
        {
            i->number = p->number;
            i->next = p->next == nullptr ? nullptr : new Entry();
            i = i->next;
        }
    }
}

復制賦值構造函數:

Stack& Stack::operator=( const Stack& s )
{
    return Stack( s );
}

調用代碼:

Stack s;
s.Push( 5 );
s.Push( 3 );

Stack s2;
s2 = s; //s2 just ends up defaulted constructed instead of copied from s

如果我替換這些行:

Stack s2;
s2 = s;

和:

Stack s2(s);

一切正常。 我在這里做錯了什么?

編輯 -

所以這里的教訓是實現分配 ctor 並在復制 ctor 中利用它,而不是像我所做的那樣反過來。

賦值運算符的行為未定義。

您正在返回一個懸空引用

編寫賦值運算符的慣用方式是std::move傳遞s object 的實例(在你的情況下,你應該按值傳遞)給 self,並返回*this作為參考。

您的賦值運算符不正確。 它返回對臨時 object 的引用。 它應該返回*this代替:

Stack& Stack::operator=( const Stack& s )
{
   // copy s to members
   return *this;
}

如果您想避免兩次實現事物,通常更容易實現賦值運算符並在復制構造函數中使用它:

Stack::Stack( const Stack& s )
:Stack()
{
  *this = s;
}

Stack& Stack::operator=( const Stack& s )
{
    if (&s == this) return *this;
    // TODO: free current members?
    if ( s.Empty() )
    {
        this->entry = nullptr;
    }
    else
    {
        this->entry = new Entry();
        Entry* i = this->entry;
        for ( Entry* p = s.entry; p != nullptr; p = p->next )
        {
            i->number = p->number;
            i->next = p->next == nullptr ? nullptr : new Entry();
            i = i->next;
        }
    }
    return *this;
}

當你這樣做

Stack& Stack::operator=( const Stack& s )
{
    return Stack( s );
}

Stack(s)創建 object,其中 scope 限制為當前 function。 然后返回對這個本地 object 的引用。

因此,在執行x = y時,不會將x修改為y的副本,並且返回對 scope 之外的 object 的引用,然后將其丟棄。

Stack& Stack::operator=( const Stack& s )的工作不是返回副本。 它的工作是修改x (稱為this )使其等於y (稱為s )。

所以,正確的方法看起來像:

Stack& Stack::operator=( const Stack& s )
{
    this->entry = new Entry();
    // then all the code to make `this` equal to `s`
}

由於您有Stack的工作副本構造函數和工作析構函數,因此您可以簡單地使用復制/交換來實現賦值運算符:

Stack& Stack::operator=( const Stack& s )
{
    if ( this != &s)
    {
       Stack temp(s);
       std::swap(temp.entry, entry);
    }
    return *this;
}

如果你有其他成員變量,你也需要交換它們。

這是通過創建一個臨時的,並簡單地將當前 object ( this ) 的成員替換為副本的成員來實現的。 然后副本與舊數據一起消失。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM