c++ - 在链表中移动和复制构造函数

标签 c++ copy-constructor doubly-linked-list class-design move-constructor

我仍在尝试了解有关复制和移动构造函数的更多信息。我有一个链接列表类,我想使用copy和move构造函数进行深度复制,但是遇到了问题。首先,要深复制List类,我只在构造函数中复制head_ and tail_。我知道代码太可怕了,也许我不应该马上跳入高级内容。
任何帮助表示赞赏!

template<typename T>
class List
{
public:

    class Node {
    public:
        Node(T value) : value_(value) {}

        T value_;
        Node* next_;
        Node* prev_;
    };

    Node* head_;
    Node* tail_;


    //! Default constructor
    List() :tail_(nullptr) {}

    //! Copy constructor
    List(const List& lst) : head_(nullptr) {

        //not sure what goes in here
        }
    }

    //! Move constructor
    List(List&& move) {
        head_ = move.head_;
        move.head_ = nullptr;
        tail_ = move.tail_;
        move.tail_ = nullptr;
    }


//! Copy assignment operator
    List& operator= (const List& list) {
        
        tail_ = nullptr;
        head_ = tail_;
    
        Node* current = list.head_;
        Node* next = list.head_->next_;
        Node* replace = head_;
        while (next != list.tail_) {
            current = current->next_;
            next = next->next_;
            replace->next_ = tail_;
            replace->next_->value_;
            replace = replace->next_;
        }
        return *this;
    }
    

    //! Move assignment operator
    List& operator= (List&& other) {        
        
        tail_ = nullptr;
        head_ = tail_;

        head_->next_ = other.head_->next_;
        Node* current = other.head_;
        Node* next = other.head_->next_;

        while (next != other.tail_) {

            current = current->next_;
            next = next->next_;
        }
        current->next_ = tail_;
        other.head_->next_ = other.tail_;

        return *this;
    }

最佳答案

这是我的五分钱。
下面的演示程序显示了如何实现复制构造函数,移动构造函数,复制赋值运算符,移动赋值运算符和析构函数,包括一些其他辅助功能。

#include <iostream>
#include <utility>
#include <functional>
#include <iterator>

template<typename T>
class List
{
private:
    struct Node 
    {
        T value;
        Node *prev;
        Node *next;
    } *head = nullptr, *tail = nullptr;

    void copy( const List &list )
    {
        if ( list.head )
        {
            head = tail = new Node { list.head->value, nullptr, nullptr };

            for ( Node *current = list.head->next; current; current = current->next )
            {
                tail = tail->next = new Node { current->value, tail, nullptr };             
            }
        }           
    }
    
public:
    //! Default constructor
    List() = default;

    //! Copy constructor
    List( const List &list )
    {
        copy( list );
    }

    //  Constructor with iterators
    template <typename InputIterator>
    List( InputIterator first, InputIterator last )
    {
        if ( first != last )
        {
            head = tail = new Node { *first, nullptr, nullptr };

            while ( ++first != last )
            {
                tail = tail->next = new Node { *first, tail, nullptr };             
            }
        }
    }

    //  Destructor
    ~List()
    {
        clear();
    }
    
    //! Move constructor
    List( List &&list ) 
    {
        std::swap( head, list.head );
        std::swap( tail, list.tail );
    }

    //! Copy assignment operator
    List & operator =( const List &list ) 
    {
        clear();
        copy( list );
        
        return *this;
    }
    
    //! Move assignment operator
    List & operator =( List &&list ) 
    {
        std::swap( head, list.head );
        std::swap( tail, list.tail );
        
        return *this;
    }
    
    void clear()
    {
        while ( head )
        {
            delete std::exchange( head, head->next );
        }
        
        tail = head;
    }
    
    void push_front( const T &value )
    {
        head = new Node{ value, nullptr, head };

        if ( !tail )
        {
            tail = head;
        }
        else
        {
            head->next->prev = head;
        }
    }

    void push_back( const T &value )
    {
        Node *new_node = new Node{ value, tail, nullptr };

        if ( tail )
        {
            tail = tail->next = new_node;
        }
        else
        {
            head = tail = new_node;
        }
    }
    
    friend std::ostream & operator <<( std::ostream &os, const List &list )
    {
        for ( Node *current = list.head; current; current = current->next )
        {
            os << current->value << " -> ";
        }
        
        return os << "null";
    }
};

int main()
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    
    List<int> list1( std::begin( a ), std::end( a ) );
    
    std::cout << list1 << '\n';
    
    list1 = List<int>( std::rbegin( a ), std::rend( a ) );

    std::cout << list1 << '\n';
    
} 
程序输出为
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
例如在此语句中
list1 = List<int>( std::rbegin( a ), std::rend( a ) );
使用了移动分配运算符。

关于c++ - 在链表中移动和复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62541663/

相关文章:

c++ - 转让独家所有权 : unique_ptr vs move semantics

c++ - 迭代器复制构造函数错误,非法作为右侧 '.' 运算符

c - 标记双向链表中的当前位置

c - C中的双向链表

java - 返回从末尾开始(向后)的双向链表的索引

c++ - Vector 不会存储正确的数据类型(wchar_t 而不是 uint16_t)

c++ - 从指向基类的指针调用派生类的复制构造?

c++ - 如何在 Visual C++ 非托管代码中编写用户定义的异常?

c++ - 具有复制分配的不同对象容器之间的自动化

c++ - 复制一个 QWidget