zoukankan      html  css  js  c++  java
  • C++ 深拷贝浅拷贝

    深拷贝用来解决浅拷贝造成的两次析构问题,因为浅拷贝时,两个指针指向同一块内存空间,析构时,一块内存空间释放两次,系统会报错。因此,我们需要重新开辟一块内存空间,使两个指针指向不同的空间,以此来解决问题。

    下面用一个String的例子来验证深拷贝。

    #include <iostream>
    #include <cstring>
    using namespace std;
    class String
    {
    public:
        //利用列表初始化为mPstr在堆上创建一个内存空间
        String(const char *s = " ") : mPstr(new char[strlen(s) + 1]) 
        {
            strcpy(mPstr,s);
        }
        //默认拷贝构造函数中,s1和s2指向同一块内存空间,当析构时,先析构s2,内存空间已经销毁,再销毁一次s1,两次析构同一个空间,报错。
        //因此,需要重新开辟一块内存空间,让s2指向新空间,析构时,各删各的
        String(const String &other) : mPstr(new char[strlen(other.mPstr) + 1]) 
        {
            strcpy(mPstr, other.mPstr);
        }
    
        ~String()
        {
            delete []mPstr;
        }
    
        void show() const
        {
            cout << mPstr << endl;
        }
    
        void append(const String &other)  //实现一个追加功能
        {
            char *p = new char[strlen(this->mPstr) + strlen(other.mPstr) + 1];
            strcpy(p, this->mPstr);
            strcat(p, other.mPstr);
            delete []this->mPstr;
            mPstr = p;
            //因为p是局部变量,所以不需要手动销毁
        }
    
        void assign(const String &other) //实现一个覆盖功能
        {
            if(this != &other)           //如果覆盖的字符是本身,就不覆盖
            {
            char *p = new char[strlen(other.mPstr) + 1];
            strcpy(p, other.mPstr);
            delete []this->mPstr;
            mPstr = p;
            }
        }
    
    private:
        char *mPstr;
    };
    
    int main(void)
    {
        String s1("Hello");
        s1.show();
        String s2(s1);
        s2.show();
        system("pause");
        return 0;
    }
    

    再来一个链表的例子

    #include <iostream>
    #include <cstring>
    using namespace std;
    //链表
    struct Node  //定义结点,实际上还是一个类,所以可以使用列表初始化
    {
        Node(int value, Node *pNext) : data(value), next(pNext){}
        int data;
        Node *next;
    };
    
    class List
    {
    public:
        List();
        //默认拷贝构造函数,会导致浅拷贝的问题,在析构时,删除同一块内存空间,报错,因此将新的pHead置空,复制数据,重新插入
        List(const List &other);
        ~List();
        void push_front(int value); //在头部插入数据
        void push_back(int value);  //在尾部插入数据
        void pop_front();           //删除头部数据
        void pop_back();            //删除尾部数据
        void clear();               //清空数据,用于析构
        void show() const;          //打印链表数据
        size_t size() const;        //记录结点个数
        bool isEmpty() const;       //判空函数
    private:
        Node *pHead;                
    };
    
    int main(void)
    {
        List l;
        l.push_front(1);
        l.push_front(2);
        l.push_front(3);
        l.show();
        cout << "***********" << endl;
        List l2(l);
        l2.show();
        system("pause");
        return 0;
    }
    
    List::List() : pHead(nullptr)
    {
    
    }
    
    List::List(const List &other) : pHead(nullptr)
    {
      Node *p = other.pHead;
      while(p)
      {
          this->push_back(p->data);
          p = p->next;
      }
    }
    
    List::~List()
    {
       clear();
    }
    
    void List::push_front(int value)
    {
        Node *pNew = new Node(value, pHead);
        pHead = pNew;
    }
    
    bool List::isEmpty() const
    {
        return nullptr == pHead;
    }
    
    void List::push_back(int value)
    {
        if(isEmpty())
        {
            push_front(value);
        }
        else
        {
            Node *pNew = new Node(value, nullptr);
            Node *p = pHead;
            while(p->next)
            {
                p = p->next;
            }
            p->next = pNew;
        }
    }
    
    void List::pop_front()
    {
        if(!isEmpty())
        {
            Node *p = pHead;
            pHead = p->next;
            delete p;
        }
    
    }
    
    void List::pop_back()
    {
        if(!isEmpty())
        {
            size_t n = size();
            if(n == 1)
            {
                pop_front();
            }
            if(n >= 2)
            {
                Node *p = pHead;
                while(p->next->next != 0)
                {
                    p = p->next;
                }
                delete p->next;
                p->next = nullptr;
            }
        }
    
    }
    
    void List::show() const
    {
        Node *p = pHead;
        while(p)
        {
            cout << p->data << endl;
            p = p->next;
        }
    }
    
    void List::clear()
    {
        while(!isEmpty())
        {
            pop_front();
        }
    }
    
    size_t List::size() const
    {
        Node *p = pHead;
        size_t counter = 0;
        while(p)
        {
            ++counter;
            p = p->next;
        }
        return counter;
    }
    
  • 相关阅读:
    用户组
    Compose
    ubuntu下不同版本python安装pip及pip的使用
    rest-framework-@action()装饰器
    数据库数据导出CSV文件,浏览器下载
    爬取拉钩网信息
    CSV模块
    DOM对象之查找标签&属性操作
    Java内存模型 一
    SQL优化之一
  • 原文地址:https://www.cnblogs.com/wsl540/p/13747277.html
Copyright © 2011-2022 走看看