• C++ 智能指针 auto_ptr 和 shared_ptr


    首先,如果你不知道什么是智能指针,请先移步:C++智能指针简单剖析

    1.auto_ptr

     1 #ifndef AUTO_PTR_H
     2 #define AUTO_PTR_H
     3 
     4 template<typename T>
     5 class auto_ptr
     6 {
     7     public :
     8         //使用explicit关键字避免隐式转换
     9         explicit auto_ptr(T* p=0);
    10         ~auto_ptr();
    11 
    12         //使用另一个类型兼容的auto_ptr来初始化一个新的auto_ptr
    13         template<typename U>
    14         auto_ptr(auto_ptr<U>& rhs);
    15 
    16         template<typename U>
    17         auto_ptr<T>& operator=(auto_ptr<U>& rhs);
    18 
    19         T& operator*() const;
    20         T* operator->() const;
    21 
    22         //返回原始对象的指针
    23         T* get() const;
    24         //放弃指针的所有权
    25         T* release();
    26         //删除原有指针并获得指针p的所有权
    27         void reset(T* p=0);
    28 
    29     private:
    30         T* pointee;
    31 };
    32 
    33 template<typename T>
    34 auto_ptr<T>::auto_ptr(T* p)
    35     :pointee(p)
    36 {}
    37 
    38 template<typename T>
    39 auto_ptr<T>::~auto_ptr()
    40 {
    41     delete pointee; //如果所有权被转移了,我们会将指针置0,delete空指针不会发生任何事
    42 }
    43 
    44 template<typename T>
    45     template<typename U>
    46 auto_ptr<T>::auto_ptr(auto_ptr<U>& rhs)
    47     :pointee(rhs.release()) //转交所有权,即rhs将所有权转交给this,并将自身指针置0
    48 {}
    49 
    50 template<typename T>
    51 template<typename U>
    52 auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<U>& rhs)
    53 {
    54     if(this!=&rhs)
    55         reset(rhs.release());
    56     return *this;
    57 }
    58 
    59 template<typename T>
    60 T& auto_ptr<T>::operator*() const
    61 {
    62     return *pointee;
    63 }
    64 
    65 template<typename T>
    66 T* auto_ptr<T>::operator->() const
    67 {
    68     return pointee;
    69 }
    70 
    71 template<typename T>
    72 T* auto_ptr<T>::get() const
    73 {
    74     return pointee;
    75 }
    76 
    77 template<typename T>
    78 T* auto_ptr<T>::release()
    79 {
    80     T* oldpointee=pointee;
    81     pointee=0; //置NULL
    82     return oldpointee; //交出所有权
    83 }
    84 
    85 template<typename T>
    86 void auto_ptr<T>::reset(T* p)
    87 {
    88     if(pointee!=p)
    89     {
    90         delete pointee; //删除原有的
    91         pointee=p; //设置新的
    92     }
    93 }
    94 
    95 #endif
     

    2.shared_ptr

    实现原理:

    当多个shared_ptr管理同一个指针,仅当最后一个shared_ptr析构时,指针才被delete。为实现这一点,我们需要一个引用计数(reference counting)。引用计数指的是,所有管理同一个裸指针(raw pointer)的shared_ptr,都共享一个引用计数器,每当一个shared_ptr被赋值(或拷贝构造)给其它shared_ptr时,这个共享的引用计数器就加1,当一个shared_ptr析构或者被用于管理其它裸指针时,这个引用计数器就减1,如果此时发现引用计数器为0,那么说明它是管理这个指针的最后一个shared_ptr了,于是我们释放指针指向的资源。

    在底层实现中,这个引用计数器保存在某个内部类型里(这个类型中还包含了deleter,它控制了指针的释放策略,默认情况下就是普通的delete操作),而这个内部类型对象在shared_ptr第一次构造时以指针的形式保存在shared_ptr中。shared_ptr在赋值和拷贝构造另一个shared_ptr时,这个指针被另一个shared_ptr共享。在引用计数归零时,这个内部类型指针与shared_ptr管理的资源一起被释放。此外,为了保证线程安全性,引用计数器的加1,减1操作都是原子操作,它保证shared_ptr由多个线程共享时不会出问题。

    下面看看一个例子:

    shared_ptr 是引用计数型(reference counting)智能指针,它在堆(heap)上放了个计数值(count)。shared_ptr 包含两个成员,一个是指向 Foo 的指针 ptr,另一个是 ref_count 指针(不一定是原始指针,有可能是 class 类型),指向堆上的 ref_count 对象。ref_count 对象有多个成员,具体的数据结构如图所示,其中 use_count为我们所说的计数,deleter 和 allocator 是可选的。

    这里写图片描述

    shared_ptr安全级别:

    • 一个 shared_ptr 对象实体可被多个线程同时读取;

    • 两个 shared_ptr 对象实体可以被两个线程同时写入,“析构”算写操作;

    • 如果要从多个线程读写同一个 shared_ptr 对象,那么需要加锁。

    具体的代码实现这里不涉及,有兴趣的朋友可以去看一看boost的实现~

  • 相关阅读:
    堪称为经典游戏设计帖整理20个点击回复超高的精品贴
    【专题报道】Google I/O开发者大会
    android用户界面之AlarmManager教程实例汇
    Android2.2 API 中文文档系列
    ruby设计模式之【观察者】模式2————更加一般化的观察者模式
    ruby中require和load的区别
    ruby/python/java全覆盖的SeleniumWebdriver系列教程(1)————快速开始
    ruby + nokogiri实现将天涯易读全帖转换成txt文件的功能
    WatirWebdriver与watir1.x的差异
    Notepad++ 的一些常用快捷键
  • 原文地址:https://www.cnblogs.com/ktao/p/7565157.html
Copyright © 2020-2023  润新知