程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++ 智能指針 auto_ptr 和 shared_ptr簡單剖析

C++ 智能指針 auto_ptr 和 shared_ptr簡單剖析

編輯:關於C++

首先,如果你不知道什麼是智能指針,請先移步:

C++智能指針簡單剖析

1.auto_ptr

#ifndef AUTO_PTR_H
#define AUTO_PTR_H

template
class auto_ptr
{
    public :
        //使用explicit關鍵字避免隱式轉換
        explicit auto_ptr(T* p=0);
        ~auto_ptr();

        //使用另一個類型兼容的auto_ptr來初始化一個新的auto_ptr
        template
        auto_ptr(auto_ptr& rhs);

        template
        auto_ptr& operator=(auto_ptr& rhs);

        T& operator*() const;
        T* operator->() const;

        //返回原始對象的指針
        T* get() const;
        //放棄指針的所有權
        T* release();
        //刪除原有指針並獲得指針p的所有權
        void reset(T* p=0);

    private:
        T* pointee;
};

template
auto_ptr::auto_ptr(T* p)
    :pointee(p)
{}

template
auto_ptr::~auto_ptr()
{
    delete pointee; //如果所有權被轉移了,我們會將指針置0,delete空指針不會發生任何事
}

template
    template
auto_ptr::auto_ptr(auto_ptr& rhs)
    :pointee(rhs.release()) //轉交所有權,即rhs將所有權轉交給this,並將自身指針置0
{}

template
template
auto_ptr& auto_ptr::operator=(auto_ptr& rhs)
{
    if(this!=&rhs)
        reset(rhs.release());
    return *this;
}

template
T& auto_ptr::operator*() const
{
    return *pointee;
}

template
T* auto_ptr::operator->() const
{
    return pointee;
}

template
T* auto_ptr::get() const
{
    return pointee;
}

template
T* auto_ptr::release()
{
    T* oldpointee=pointee;
    pointee=0; //置NULL
    return oldpointee; //交出所有權
}

template
void auto_ptr::reset(T* p)
{
    if(pointee!=p)
    {
        delete pointee; //刪除原有的
        pointee=p; //設置新的
    }
}

#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的實現~

   
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved