C++ 重载运算符=,类C+中的麻烦析构函数+;

C++ 重载运算符=,类C+中的麻烦析构函数+;,c++,C++,我正在尝试实现一个单向列表。在命令m3=m1+m2在主功能中加倍之前,一切都非常正常。在调试时,我注意到在重载=运算符中,在销毁发生后,分配给o1对象的值消失。不知道析构函数是否有问题,或者运算符= 代码如下: #include <iostream> using namespace std; template <class T> class Element; template <class T> class List{

我正在尝试实现一个单向列表。在命令m3=m1+m2在主功能中加倍之前,一切都非常正常。在调试时,我注意到在重载=运算符中,在销毁发生后,分配给o1对象的值消失。不知道析构函数是否有问题,或者运算符=

代码如下:

#include <iostream>
using namespace std;

    template <class T>
    class Element;

    template <class T>
    class List{
        friend class Element<T>;
        Element<T> *head;
    public:
        List(){
            cout<<"konstruktor"<<endl;
            head=NULL;
        }
        ~List() {
            Element<T> *tmp = head;
            cout << "destruktor" << endl;
            while (tmp) {
                //tmp = tmp->next;
                delete head;
                head = tmp;
            }
        }
        friend istream &operator>>(istream &p, List<T> &o1){
            Element<T>* new_ele;
            Element<T>* it;
            it=o1.head;
            new_ele=new Element<T>;
            p>>new_ele->value;
            new_ele->next=NULL;
            if (o1.head==NULL){
                o1.head=new_ele;
            }
            else{
                while (it->next!=NULL){
                    it=it->next;
                }
                it->next=new_ele;
            }
            return p;
        }
        friend ostream &operator<<(ostream &s, List<T> &o1){
            Element<T>* it;
            it=o1.head;
            while(it){
                s<<it->value<<" ";
                it=it->next;
            }
            return s;
        }
        List <T> &operator=(const List<T> &o1){
            if (this==&o1){
                return *this;
            }
            Element<T> *it1, *it2, *itc;
            this->~List();//this is the where everything goes haywire
            itc=head;
            it1=o1.head;
            while(it1){
                itc=new Element<T>;
                if (!head) head=it1;
                itc->next=NULL;
                itc->value=it1->value;
                it1=it1->next;
                itc=itc->next;
            }
            return *this;
        }

        List<T> &operator+(List<T> &o1){
            if(o1.head==NULL){
                return *this;
            }else if(head==NULL){
                return o1;
            }
            static List<T> res=*this;
            Element<T> *it;
            it=res.head;
            while(it->next) {
                it = it->next;
            }
            Element <T> *o1_it=o1.head;
            while(o1_it){
                Element<T> *copy;
                copy=new Element<T>;
                copy->next=NULL;
                copy->value=o1_it->value;
                it->next=copy;
                it=it->next;
                o1_it=o1_it->next;
            }
            return res;
        }

        int length_list(){
            Element<T> *it;
            int count_elements=0;
            it=head;
            while(it->next){
                count_elements++;
                it=it->next;
            }
            return count_elements;
        }

        void bubblesort_List(){
            Element<T> *it;
            for(int i=0; this->length_list() > i;i++){
                it = head;
                while (it->next) {
                    if (it->next->value < it->value) {
                        T tmp = it->value;
                        it->value = it->next->value;
                        it->next->value = tmp;
                    }
                    it = it->next;
                }
            }
        }
    };

    template <class T>
    class Element{
        friend class List<T>;
        friend istream &operator>>(istream &p, List<T> &o1);
        friend ostream &operator<<(ostream &s, List<T> &o1);

        Element<T> *next;
        T value;
    public:
        Element(){
            next=NULL;
        }
    };
    int main(){

        List<int> m1, m2, m3;

        cin>>m1>>m1>>m1;
        cin>>m2;
        m3=m1+m2;
        m3=m1+m2;
        cout<<m3<<endl;

        return 0;
    }
#包括
使用名称空间std;
模板
类元素;
模板
班级名单{
友元类元素;
元素*头;
公众:
列表(){
库特价值;
新建元素->下一步=空;
if(o1.head==NULL){
o1.水头=新的水头;
}
否则{
while(it->next!=NULL){
it=it->next;
}
it->next=新建;
}
返回p;
}
friend ostream&operatorvalue;
it1=it1->next;
itc=itc->next;
}
归还*这个;
}
列表和操作员+(列表和o1){
if(o1.head==NULL){
归还*这个;
}else if(head==NULL){
返回o1;
}
静态列表res=*this;
元素*it;
it=res.head;
while(it->next){
it=it->next;
}
元素*o1_it=o1.head;
while(o1_it){
元素*副本;
复制=新元素;
复制->下一步=空;
复制->值=o1\u it->值;
它->下一步=复制;
it=it->next;
o1_it=o1_it->next;
}
返回res;
}
int length_list(){
元素*it;
int count_元素=0;
它=头;
while(it->next){
计数元素++;
it=it->next;
}
返回计数元素;
}
void bubblesort_List(){
元素*it;
对于(int i=0;this->length\u list()>i;i++){
它=头;
while(it->next){
如果(it->next->valuevalue){
T tmp=it->value;
it->value=it->next->value;
it->next->value=tmp;
}
it=it->next;
}
}
}
};
模板
类元素{
好友类列表;
friend istream&operator>>(istream&p,列表&o1);
friend ostream&operatorm1>>m1>>m1;
cin>>m2;
m3=m1+m2;
m3=m1+m2;
两个主要问题

  • 调用delete调用析构函数,不要显式调用~List。只需调用free_List或其他什么,然后直接调用它
  • 你的析构函数坏了,不能正确释放内存
你想要:

void free_list (Element<T> * head) {
   Element<T> *tmp = head;
   while (tmp != null) {
     head = tmp.next;
     delete tmp;
     tmp = head;
   }
}
void free_列表(元素*头){
元素*tmp=头部;
while(tmp!=null){
head=tmp.next;
删除tmp;
tmp=头部;
}
}
这会破坏对象,而不仅仅是运行析构函数

当一个对象被销毁后,它的存储仍然存在,但那个里并没有对象。和存储交互就像有一个对象一样,存在未定义的行为

将析构函数体移动到名为
clear()
的辅助函数:

修复它:

    clear() {
        std::cout << "clear" << std::endl;
        while (head) {
          Element<T>* tmp = head;
          head=head->next;
          delete tmp;
        }
    }
我把所有的东西都链接起来,以实现更简单的功能

=(&&)
(&&)
(移动分配和移动构造)复制
头并清除源代码。这是少量重复代码

=(const&)
(copy assign)使用
=(&&)
(move assign)和
(const&)
(copy construct)。复制节点很难,只需在一种情况下执行。复制到空实例比复制到已经存在的实例更容易

(const&)
是唯一做这项工作的。在这里,我保留了一个指向链接列表尾部指针的指针,以及一个指向要添加的下一个元素的指针


然后,我在中拼接下一个元素的副本,并更新尾部和下一个元素指针。

从不显式调用析构函数。虽然存在罕见的异常,但在生活中不太可能遇到它们。
    clear() {
        std::cout << "clear" << std::endl;
        while (head) {
          Element<T>* tmp = head;
          head=head->next;
          delete tmp;
        }
    }
    List& operator=(List&&o) {
      if (this==&o)
        return *this;
      clear();
      head = o.head;
      o.head = nullptr;
      return *this
    }
    List& operator=(const List &o) {
      if (this== &o)
        return;
      *this = List(o); // call operator=(List&&) using a copy of o
      return *this;
    }
    List(List&& o):
      head(o.head)
    {
      o.head = nullptr;
    }
    List():head(nullptr) {}
    // all of the work goes on here:
    List(List const& o):List()
    {
      Element<T>* src = o.head;
      Element<T>** dest = &head;
      while(src) {
        *dest = new Element<T>;
        (*dest)->value = src->value;
        (*dest)->next = nullptr;
        src = src->next;
        dest = &((*dest)->next);
      }
    }