简体   繁体   中英

Linked List Copy/Move semantic C++

so I have this code for linked list below. I need to create copy/move constructors and operators. I am having troubles how to make it the right way.

I know the code isn't perfect, I will appreciate all tips, but I want to focus mainly on copy/move semantic.

#include <iostream>
#include <string>
#include <stdexcept>

using namespace std;

class List {
    class Node {
        Node* next;
        string text;
        int index;
        friend class List;
      public:
        Node(const string& value, int i) : next(nullptr), index(i), text(value) {}
        friend ostream& operator<< (ostream& wy, const Node& wzl) {
            if (wzl.next) return wy << wzl.text << ", " << *wzl.next;
            else return wy << wzl.text;
        }
    };

    Node* head;

    int _size(Node* node, int size = 0) { 
        if (node == NULL) {
            return size;
        } else {
            _size(node->next, size+1);
        }
    }

    void _insert(Node* node, const string& value, int index) {
        if (node->next == NULL || node->next->index > index) {
            if (node->index == index) {
                node->text = value;
            } else {
                Node* element = new Node(value, index);
                element->next = node->next;
                node->next = element;
            }
        } else {
            _insert(node->next, value, index);
        }
    }

    string _read(Node* node, int index) {
        if (node->next != NULL && node->next->index <= index) {
            return _read(node->next, index);
        } else if (node->index == index) {
            return node->text;
        } else {
            throw invalid_argument("No such index");
        }
    }

    void _remove(Node* node, int index) {
        if (node->next != NULL && node->next->index < index) {
            _remove(node->next, index);
        } else if (node->next->index == index) {
            Node* temp;

            if (node->next->next != NULL) {
                int temp_index = node->next->next->index;
                temp = new Node(node->next->next->text, temp_index);
                if (node->next->next->next != NULL) { 
                    temp->next = node->next->next->next;
                } else {
                    temp->next = NULL;
                }
                temp->index = node->next->next->index;
            } else {
                temp = nullptr;
            }

            delete node->next;
            node->next = temp;
        } else {
            throw invalid_argument("No such index");
        }
    }

public:
    List() : head(nullptr){};
    List(const List &lst) : head(nullptr) {
        Node* tmp_lst = lst.head;
        Node* tmp_this = this->head;

        while (tmp_lst != NULL) {
            // cerr << this->head->text;
            tmp_this = new Node(tmp_lst->text, tmp_lst->index);
            tmp_this = tmp_this->next;
            tmp_lst = tmp_lst->next;
        }
    }
    List(List&& lst);
    List(initializer_list<string> lst) : List() {
        Node* tmp;
        int pos = 0;
        for (auto element : lst) {
            if (this->head != NULL){
                tmp->next = new Node(element, pos);
                tmp = tmp->next;
                pos++;
            } else {
                this->head = new Node(element, pos);
                tmp = this->head;
                pos++;
            }
        }
    };
    List& operator= (const List& lst) {
        if (this != &lst) {
            delete this->head;

            this->head = nullptr;

            Node* tmp_lst = lst.head;
            Node* tmp_this = this->head;

            while (tmp_lst != NULL) {
                tmp_this = new Node(tmp_lst->text, tmp_lst->index);
                tmp_this = tmp_this->next;
                tmp_lst = tmp_lst->next;
            }
        }
        return *this;
    }
    List& operator= (List&& lst);
    ~List(){
        delete head;    
    };

    void insert(const string& value, int pos) {
        if (pos < 0) {
            throw invalid_argument("Position cant be negative");
        }

        if (this->head == NULL) {
            Node* new_head = new Node(value, pos);
            this->head = new_head;
        } else if (this->head->index > pos) {
            Node* new_head = new Node(value, pos);
            new_head->next = this->head;
            this->head = new_head;
        } else {
            _insert(this->head, value, pos);
        }
    }

    string read(int pos) {
        return _read(this->head, pos);
    }    

    int size() {
       return _size(this->head);
    }

    void remove(int pos) {
        return _remove(this->head, pos);
    }

public:
    friend ostream& operator<< (ostream& wy, const List& lst) {
        if (lst.head) return wy << "(" << *lst.head << ")";
        else return wy << "()";
    }
};

int main() {
    return 0;
}

You List copy-constructor is severely flawed:

  • You initialize tmp_this to the value of this->head which is a null pointer
  • The above doesn't matter because the first thing you do in the loop is reassign tmp_this to point to a new Node object.
  • Then you immediately discard that pointer, by reassigning tmp_this to point to tmp_this->next which is a null pointer.
  • And you don't link anything into the list.

A working function could look something like

List(const List &lst) : head(nullptr) {
    Node* tmp_lst = lst.head;
    Node** tmp_current = &head;

    while (tmp_lst != NULL) {
        Node* tmp_this = new Node(tmp_lst->text, tmp_lst->index);

        // Would prefer to use the copy-constructor here too, instead of the above
        // Node* tmp_this = new Node(tmp_lst);

        // This links the new node into the end of the list
        *tmp_current = tmp_this
        tmp_current = &tmp_this->next;

        tmp_lst = tmp_lst->next;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM