C ++中单链接列表赋值运算符重载

时间:2015-11-22 18:47:27

标签: c++ singly-linked-list

我有以下单链表实施。

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;
        }
    }


};

根据类的当前实现和复制构造函数,有人可以帮助赋值运算符重载。另外,我对复制构造函数和赋值重载有点困惑。我的理解是复制构造函数创建一个新列表,它与旧列表中的旧列表具有相同的值。这个所有节点的下一个地址将是不同的,但值是相同的,因为它是一个深拷贝。我的理解是正确的,然后是分配重载的内容吗?

2 个答案:

答案 0 :(得分:5)

如果您已经有了复制构造函数和析构函数,那么还要实现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
    

答案 1 :(得分:1)

您需要考虑以下情况:

  • 复制构造,即slist<int> newone = 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,那么你还有一个移动构造函数和一个移动赋值运算符可能想要实施。

如评论中所述,您的深层复制算法不正确:您需要复制每个节点:

// 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而不是原始指针。