簡體   English   中英

移動分配運算符C ++

[英]Move Assignment operator c++

我無法確定我的移動分配運算符出了什么問題,這里是函數。 我認為我沒有正確地獲取數據,因為運行測試時,我得到一個隨機的負數,並且“您的程序已停止工作”

virtual LinkedList<T> &operator=(LinkedList<T> &&other)
{
    cout << " [x] Move *assignment* operator called. " << endl;

    // Delete our own elements
    ListNode<T> *temp1 = _front;
    while (temp1 != nullptr)
    {
        ListNode<T> *n = temp1->getNext();
        delete temp1;           
        temp1 = n;
    }
    // Grab other data for ourselves
    ListNode<T> *temp2 = other._front;
    while (temp2 != nullptr)
    {
        addElement(temp2->getValue());
        temp2 = temp2->getNext();
    }
    // Reset their pointers to nullptr

    other._front = nullptr;
    other._end = nullptr;
    other._size = 0;
    other._last_accessed_index = 0;
    other._last_accessed_node = nullptr;

    return *this;
}

測試代碼-這是我老師的測試代碼-

// Use move *assignment* operator
cout << " [x] Test #5: Move *assignment* constructor behavior" << endl;
moved1 = LinkedList<int>{ 6, 7, 8, 9, 10 };
cout << "   [x] Result:" << endl;
cout << "   [x]  Expected:\t6 7 8 9 10" << endl;
cout << "   [x]  Actual:\t\t";
for (int i = 0; i < moved1.getSize(); i++)
{
    cout << moved1.getElementAt(i) << " ";
}
cout << endl << endl;

這是我第一次使用move和移動分配運算符。 謝謝 :)

這不是移動分配運算符的正確實現。 它看起來更像是一個副本分配運算符(但不是一個好的運算符,因為它會泄漏內存)。

一個典型的移動分配運算符將看起來像這樣:

#include <utility>

LinkedList<T>& operator=(LinkedList<T> &&other)
{
    cout << " [x] Move *assignment* operator called. " << endl;

    std::swap(_front, other._front);
    std::swap(_end, other._end);
    std::swap(_size, other._size);
    std::swap(_last_accessed_index, other._last_accessed_index);
    std::swap(_last_accessed_node, other._last_accessed_node);

    return *this;
}

移動分配操作員不應釋放任何東西 源內容的所有權移到目標對象,反之亦然。 在賦值運算符退出后銷毀源對象時,讓源對象釋放目標對象的先前內容,因此請確保該類還具有適當的析構函數實現:

~LinkedList()
{
    // Delete our elements
    ListNode<T> *temp = _front;
    while (temp != nullptr)
    {
        ListNode<T> *n = temp->getNext();
        delete temp;           
        temp = n;
    }
}

為了達到良好的效果,這是復制構造函數,移動構造函數和復制賦值運算符的外觀:

LinkedList() :
    _front(nullptr),
    _end(nullptr),
    _size(0),
    _last_accessed_index(0),
    _last_accessed_node(nullptr)
{
    cout << " [x] Default *constructor* called. " << endl;
}

LinkedList(const LinkedList<T> &src)
    : LinkedList()
{
    cout << " [x] Copy *constructor* called. " << endl;

    ListNode<T> *temp = src._front;
    while (temp != nullptr)
    {
        addElement(temp->getValue());
        temp = temp->getNext();
    }
}

LinkedList(LinkedList<T> &&src)
    : LinkedList()
{
    cout << " [x] Move *constructor* called. " << endl;    
    src.swap(*this);
}

LinkedList(initializer_list<T> src)
    : LinkedList()
{
    cout << " [x] Initialization *constructor* called. " << endl;

    const T *temp = src.begin();
    while (temp != src.end())
    {
        addElement(*temp);
        ++temp;
    }
}

LinkedList<T>& operator=(const LinkedList<T> &other)
{
    cout << " [x] Copy *assignment* operator called. " << endl;

    if (&other != this)
        LinkedList<T>(other).swap(*this);

    return *this;
}

LinkedList<T>& operator=(LinkedList<T> &&other)
{
    cout << " [x] Move *assignment* operator called. " << endl;
    other.swap(*this);        
    return *this;
}

void swap(LinkedList<T> &other)
{
    std::swap(_front, other._front);
    std::swap(_end, other._end);
    std::swap(_size, other._size);
    std::swap(_last_accessed_index, other._last_accessed_index);
    std::swap(_last_accessed_node, other._last_accessed_node);
}

復制和移動賦值運算符實際上可以合並在一起,形成一個實現,方法是按值取輸入對象,並讓編譯器根據調用該運算符的上下文來決定在初始化該對象時是使用復制還是移動語義。 :

LinkedList<T>& operator=(LinkedList<T> other)
{
    cout << " [x] *assignment* operator called. " << endl;
    swap(other);
    return *this;
}

如果沒有其余代碼,很難確定,但是看起來您沒有正確清除分配的列表。

當您這樣做時:

// Delete our own elements
ListNode<T> *temp1 = _front;
while (temp1 != nullptr)
{
    ListNode<T> *n = temp1->getNext();
    delete temp1;           
    temp1 = n;
}

您實際上並沒有從this刪除元素。 因此, moved1包含已刪除的節點,並且當您開始循環訪問它們時,執行將失敗。 您要做的就是在刪除節點之前從列表中刪除它們。

要走的路是:

// Remove our own elements
ListNode<T> *temp1 = _front;
while (temp1 != nullptr)
{
    ListNode<T> *n = temp1->getNext();
    pop();
    delete temp1;           
    temp1 = n;
}

並有如下方法:

void pop() // removes the first element from the list
{ 
    _front = _end._front; 
    _end = _end._end; 
    --_size; 
}

當然pop的定義將取決於您對類的完整實現。 如果要存儲指向給定對象的指針,則可能不應刪除這些指針。 但是,如果使用附加的包裝器(例如ListNode ,則pop方法應刪除它們-盡管在包裝器的情況下,最好不要使用任何指針。

您可以查看std :: list :: pop_front以獲得更多信息。

暫無
暫無

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

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