zoukankan      html  css  js  c++  java
  • C++中的浅拷贝、深拷贝、智能指针

    浅拷贝(shallow copy)与深拷贝(deep copy)对于值拷贝的处理相同,都是创建新对象,但对于引用拷贝的处理不同,深拷贝将会重新创建新对象,返回新对象的引用字。浅拷贝不会创建新引用类型。


    怎么判断一个类的赋值构造函数的方法:根据类的实现
    1。如果它有一个用原生指针指针实现的对象引用,或是用boost::shared_ptr等引用分享所有权的智能指针实现的对象引用,则这个拷贝是浅拷贝
    2。如果是用copy_ptr这种实现了深拷贝的智能指针实现的对象引用,就是深拷贝了。copy_ptr在内部保留一个指针,当它自己解析时,它同时也销毁它在内部保存的这个指针。
    最能体现深层拷贝与浅层拷贝的,就是‘=’的重载。我们以此为例。
    例1:浅拷贝
    class string
    {
      char *m_str; //对象之中含有指针数据类型
    public:
      string(char *s)
      {
        m_str=s;
      }
      string(){};
      string&operator=(const string s)
      {
        m_str=s.m_str; //s1,s2指向同一个内存
        return *this}
      };
      int main()
      {
        string s1("abc"),s2;
        s2=s1;
        cout<<s2.m_str;
      }
    };
    例2:深拷贝
    string&operator=(const string&s)
    {
      if(strlen(m_str)!=strlen(s.m_str))
      m_str=new char[strlen(s.m_str)+1]; //为被赋值对象申请了一个新的内存
      if(*this!=s)
        strcmp(m_str,s.m_str);
      return *this;
    }
    浅拷贝易使对象的值发生不必要的改变。这时我们需要智能shared_ptr指针来管理。
    例:
    #include <vector>
    using namespace std;
    using namespace boost;
     
    int main (int argc, const char * argv[])
    {
     
        typedef vector< shared_ptr > sharedContainers;
        sharedContainers sharedArray(10);
        int i=0;
        for(sharedContainers::iterator pos = sharedArray.begin() ;pos!=sharedArray.end();++pos) 
        {
            *pos = make_shared(++i);
        }
        cout<<"sharedArray[5]的初始值:"<<*sharedArray[5]<<endl;
        cout<<"sharedArray[5]的初始引用计数为:"<<sharedArray[5].use_count()<<endl;
        shared_ptr p1 = sharedArray[5];
        *p1 = 10;
        cout<<"sharedArray[5]经过赋值后的值:"<<*sharedArray[5]<<endl;
        cout<<"sharedArray[5]赋值后的引用计数为:"<<sharedArray[5].use_count()<<endl;
        shared_ptr p2(sharedArray[5]);
        cout<<"sharedArray[5]复制后的引用计数为:"<<sharedArray[5].use_count()<<endl;
        return 0;
    }
    其输出结果为:
      sharedArray[5]的初始值:6
      sharedArray[5]的初始引用计数为:1
      sharedArray[5]经过赋值后的值:10
      sharedArray[5]赋值后的引用计数为:2
      sharedArray[5]复制后的引用计数为:3
     
    shared_ptr简单实现(主旨:引用计数reference count):

    1.一个模板指针T* ptr,指向实际的对象。

    2.创建类的新对象时,初始化指针并将引用计数置为1。

    3.重载operator*和operator->,使得能像指针一样使用shared_ptr。

    4.重载copy constructor,使其引用次数等于右操作数所指对象加一。

    5.重载operator=,如果原来的shared_ptr已经有对象,则让其引用次数减一并判断引用是否为零(是否调用delete)。

     然后将新的对象引用次数加一。

    6.重载析构函数,使引用次数减一并判断引用是否为零(是否调用delete)。  

    #ifndef __SHARED_PTR_
    #define __SHARED_PTR_
    
    template <typename T>
    class shared_ptr {
    public:
        shared_ptr(T* p) : count(new int(1)), _ptr(p) {}
        shared_ptr(shared_ptr<T>& other) : count(&(++*other.count)), _ptr(other._ptr) {}
        T* operator->() { return _ptr; }
        T& operator*() { return *_ptr; }
        shared_ptr<T>& operator=(shared_ptr<T>& other)
        {
            ++*other.count;
            if (this->_ptr && 0 == --*this->count)
            {
                delete count;
                delete _ptr;
            }
            this->_ptr = other._ptr;
            this->count = other.count;
            return *this;
        }
        ~shared_ptr()
        {
            if (--*count == 0)
            {
                delete count;
                delete _ptr;
            }
        }
        int getRef() { return *count; }
    private:
        int* count;
        T* _ptr;
    };
    
    
    #endif
  • 相关阅读:
    Java静态方法中使用注入类
    Java FTP辅助类
    Java SFTP辅助类
    MyBatis学习总结——批量查询
    MyBatis学习总结—实现关联表查询
    Redis集群搭建与简单使用
    SQL管理工具
    MySQL锁机制
    MySQL权限管理
    yii框架下使用redis
  • 原文地址:https://www.cnblogs.com/qionglouyuyu/p/4620714.html
Copyright © 2011-2022 走看看