簡體   English   中英

C ++中的單鏈列表分配運算符重載

[英]Singly linked list assignment operator overload in C++

我有以下單鏈接列表實現。

template <typename T> struct node{
    node(T data):data(data),next(nullptr){}
    T data;
    node<T> * next;
};

template< typename T> class slist{
    node<T>* head;
    int size;
public:
    slist(node<T>* head):head(head), size(0){}

    slist(const slist<T>& rhs){

        node<T>* temp = rhs.getHead();
        node<T>* p = new node<T>(temp->data);
        head = p;
        node<T>* current = p;
        while(temp != nullptr){
            current = current->next;
            current->data = temp->data;
        }

    }
    ~slist(){
        if(head == nullptr) return;

        while(head != nullptr){
            node<T>* current = head;
            head = head->next;
            delete(current);
        }
    }
    slist& operator= (const slist& rhs){


    }
    node<T>* getHead()const {
        return head;
    }


    void insertFront(T item){
        node<T>* p = new node<T>(item);
        if(head == nullptr){
            p = head;
            size++;
            return;
        }
        p->next = head;
        head = p;
        size++;
    }

    void insertBack(T item){
        node<T>* p = new node<T>(item);
        node<T>* current = head;
        while(current->next != nullptr){
            current = current->next;
        }
        current->next = p;
        size++;
    }

    void remove(T item){
        bool check = false;

        node<T>* current = head;
        try {
            while(current != nullptr){
                if(current->data == item) check = true;
                current = current->next;
            }
            if(!check){
                throw std::runtime_error("Item not in list");

            }
        }catch(std::runtime_error& e){
            std::cout<<e.what()<<std::endl;
            exit(-1);
        }

        current = head;
        while(current != nullptr){
           if(current->next->data == item){
               node<T>* temp = current->next;
               current->next = current->next->next;
               delete(temp);
               break;
           }
            current = current->next;
        }
        size--;

    }
    int getSize () const {
        return size;
    }

    void printList(){
        node<T>* current = head;
        while(current != nullptr){
            if(current->next != nullptr){
                std::cout<<current->data<<"->";
            }else{
                std::cout<<current->data<<std::endl;
            }
            current = current->next;
        }
    }


};

基於類和副本構造函數的當前實現,有人可以幫助分配運算符重載。 我對復制構造函數和賦值重載也有些困惑。 我了解的是,復制構造函數會創建一個新列表,該列表的值與舊列表中的舊列表相同。 所有節點的下一個地址將有所不同,但由於是深度復制,因此值將相同。 我的理解是正確的,然后分配超負荷做什么?

如果您已經具有復制構造函數和析構函數,則還應實現swap() ,然后根據以下三個方面實現復制賦值運算符,例如:

template <typename T>
slist<T>& slist<T>::operator= (slist<T> other) {
    this->swap(other);
    return *this;
}

請注意,該參數很容易復制:與復制構造函數不同,復制分配可以按值接受其參數。

關於語義:

  • 復制構造函數創建一個與原始對象具有相同值的新對象,例如:

     slist<int> sl1; // insert elements into sl1 slist<int> sl2(sl1); // uses the copy constructor 
  • 復制分配將現有對象的值替換為分配值的值,例如

     slist<int> sl1; slist<int> sl2; // possibly modify both sl1 and sl2 sl2 = sl1; // uses the copy assignment operator 

您需要考慮以下情況:

  • 復制構造,即slist<int> newone = other;
  • 復制分配,即slist<int> a; /* ... */ a = other; slist<int> a; /* ... */ a = other;

現在,這兩個操作都構成了-顧名思義-原始數據結構的副本。 確切的含義取決於您要如何實現,但以下幾點應-保持最不令人驚訝原則 -成立:

slist<int> a = some_generator(), b = another_generator();
slist<int> c = a;
// a == c should be true
b = a;
// a == b should be true now
modify(a);
// a == b should be false now, BUT b should be in the same state as before!

實現此目標的最簡單方法是制作深層副本(正如您已經建議的那樣)。 因此,您基本上可以執行與復制構造函數相同的操作。 制作每個節點的副本,以使其具有與原始節點相同的值,但它們是不同的實體。

如果您還針對“現代C ++”(即C ++ 11及更高版本),那么您可能想要實現一個move構造函數和一個move賦值運算符


如評論中所述,您的深層復制算法不正確:您需要制作每個節點的副本:

// if in assigment, delete the nodes pointed to by head first!
node<T> const * iterator = other.getHead();
if (iterator != nullptr) { // in your implementation, head could be a nullptr
  node<T> * new_node = new node<T>(*iterator); // make a copy of head
  head = new_node;
  while (iterator->next) {
    iterator = iterator->next;
    node<T> * copy = new node<T>(*iterator);
    new_node->next = copy;
    new_node = copy;
  }
  new_node->next = nullptr;
}

另外,如果可以的話,在這種情況下,最好使用智能指針unique_ptr ,而不是原始指針。

暫無
暫無

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

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