zoukankan      html  css  js  c++  java
  • 关于智能指针的研究

    最近面试的时候面试官问了我一个问题。unique_ptr和shared_ptr到底有什么区别?我一时语塞。回来之后我痛定思痛,决定好好的研究一下智能指针的问题。现在已经研究的差不多了,决定好好的总结一下。

      一、智能指针的用途

      二、智能指针的特性

      三、智能指针的种类与用途

        3.1 最原始的智能指针auto_ptr

        3.2 独一无二的智能指针unique_ptr

        3.3 可以共享的指针shared_ptr

        3.4 智能指针的用途

          3.4.1 智能指针的用途

          3.4.2 unique_ptr和shared_ptr的用途

      四、总结

      一、智能指针的用途

      首先我们先设置一种场景,假如我们当前有一个类,类中存放着一个指针用来保存字符串,那么我们应该怎么写呢?

      class CopyConstructor
      {
      public:
          char *p;
      public:
          CopyConstructor(char *str);
          virtual ~CopyConstructor();
          CopyConstructor(CopyConstructor &m_copCon);
          CopyConstructor operator = (const CopyConstructor &m_copCon);
     
          void print();
      };
      好的,那么我们再构造函数中如果想要初始化字符串可以这样写。  
      CopyConstructor::CopyConstructor(char *str)
      {
        cout<<"CopyConstructor::CopyConstructor"<<endl;
        p = new char[strlen(str) + 1];
        strncpy(p, str, strlen(str) + 1);
      }
      
      如果我们现在提出一个需求,就是要让两个对象之间可赋值,就像这样:
      CopyConstructor copConFirst(str);
           CopyConstructor copConSecond(str2);
            copConSecond = copConFirst;
      但是如果这样写的话就会面临一个问题,就是析构函数怎么写?换句话说再析构函数中是否使用delete函数回收之前new出来的空间。那么我们分析一下这个问题
      假如我们不写delete函数,那么当然程序就会导致内存泄漏了,这个恐怕是不成的。
      假如我们写delete函数,那么会导致一个什么结果呢?它只拷贝了指针,但是实际delete掉的是同一个内存空间,会直接导致段错误的。
      好的,为了解决这个问题,我们有三种方法可以解决:
      (1)写一个运算符重载函数,重载=,关于这个的写法请大家参考我的博客《关于拷贝构造函数和运算符重载的问题》。
      (2)使用智能指针。
     
      二、智能指针的特性
       那么为什么智能指针能解决上述问题呢?因为他有两个特性。第一个特性就是自动进行delete,换句话说就算你不写delete那么它也能再最后回收那块空间,绝对不会说内存泄漏这种情况发生。第二个特性就是智能指针是一个指针跟一个空间相对应。(我们先不讨论shared_ptr)。这样就不会导致delete两次了。
      三、智能指针的种类和用途
       3.1 最原始的智能指针auto_ptr
        auto_ptr是最原始的智能指针。他有以下几个特性:1、只要是c++的版本,都能使用auto_ptr,不像后面两种必须使用c++11的版本才行。2、auto_ptr再相互赋值时,会先把原来的指针移成空,然后再把新来的指针指向原来的指针指向的空间。3、auto_ptr只能支持delete,不支持delete []。当然了,它的特性来说的话还是都支持的。
      3.2 独一无二的智能指针unique_ptr
        正因为有上述第二,第三两个问题,因此c++11才出了unique_ptr,它的特性如下:1、unique_ptr是只有c++11版本才能使用的。因此再编译或者再编写makefile的时候要注意以下。2、unique_ptr再相互赋值的时候不能使用=(即copConSecond = copConFirst这样写不可以的)。必须要有恰当的函数。3、unique_ptr可以支持delete []。
        这里稍微说以下如何用unique_ptr进行相互赋值,这当中有三种情况,第一种情况是两个指针都是unique_ptr,第二个情况是我要把unique_ptr变成普通指针,第三种情况是我要把普通指针变成unique_ptr。我们举个例子 
      unique_ptr <AutoPtr> autoPtrFirst(new AutoPtr(1));
           unique_ptr <AutoPtr> autoPtrSecond(new AutoPtr(2));
      AutoPtr *p = NULL;
      好,我们针对以上三种情况进行讨论。
      第一种情况:假如我们要把autoPtrSecond指向autoPtrFirst那么我们应该怎么做呢?我们可以这样写。autoPtrSecond = std::move(autoPtrFirst),即把First指针移动走,只留下Second指针。
      第二种情况:如果我要把unique_ptr指针变成普通指针应该怎么做呢?我们可以这样写。p = autoPtrFirst.release(),这样我们就可以把autoPtrFirst移动走,然后让p指向原来的地址空间了。
      第三种情况:如果我们要把普通指针变成unique_ptr指针应该怎么做呢?我们可以这样写。autoPtrFirst.reset(p),这样我们就可以将autoPtrFirst指向p了。
     
      3.3 可以进行共享的指针
      好的,那么我们看完了前两种智能指针我们可能会产生一个问题:为啥不能两个智能指针指向同一块内存空间呢?答案是可以的。我们使用shared_ptr就可以了。
      关于shared_ptr里面的实现方法我们再这里不做过多的研究和探讨。我们只研究shared_ptr里面的特性。它的特性有如下几点:1、shared_ptr是只有c++11版本才能使用的。因此再编译或者再编写makefile的时候要注意一下。2、shared_ptr和前两者最大的不同在于它支持两个指针指向同一块内存。3、shared_ptr支持delete []。
      3.4 智能指针的用法
        3.4.1 智能指针的用途
          智能指针对于动态分配内存来说非常的方便,但是有以下几个缺点:
          1、智能指针相当于是传指针,这样比传对象要麻烦不少。  
          2、智能指针不太容易知道什么时候结束这个对象,因此对我们分析代码不是一个好的选择。
        3.4.2 关于unique_ptr和shared_ptr的用途
          首先说明一下,auto_ptr这个基本上到c++11以后就被弃用了,基本用的还是后两种。前者一般来说有比较好的安全管理机制,后者来说比较方便。所以各有优劣。
      四、总结
        本文主要研究了智能指针的用途,种类,区别等等。
     
     
         
     
     
     
     
     
  • 相关阅读:
    NSURLSession实践(结合POST和GET请求JSON和XML数据)
    自己写的一个图片轮播器
    UIImage的一些使用技巧
    NSURLSession学习
    升级Xcode7之后的适配问题(插件、ATS等)
    UITabBarController详解
    解析xml && json
    [11]UITableView编辑 删除 添加 移动 单例 及其去掉TableView没内容的Cell
    nonatomic, retain,weak,strong用法详解
    [10]UITableView表示图2 自适应高度
  • 原文地址:https://www.cnblogs.com/songyuchen/p/12915293.html
Copyright © 2011-2022 走看看