1. 程式人生 > >智慧指標 shared ptr 的使用方法

智慧指標 shared ptr 的使用方法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

基於Boost庫, C++11 加入了shared_ptrweak_ptr. 它們最早在TR1中就被引入, 但在C++11中, 在Boost的基礎上又加入了新的功能.

std::shared_ptr

使用引用計數. 每一個shared_ptr的拷貝都指向相同的記憶體. 在最後一個shared_ptr析構的時候, 記憶體才會被釋放.


    
 std::shared_ptr<int> p1(new int(5));std::shared_ptr<int> p2 = p1; // 都指向同一記憶體. p1.reset(); // 因為p2還在,所以記憶體沒有釋放.p2.reset(); // 釋放記憶體, 因為沒有shared_ptr指向那塊記憶體了.std::shared_ptr 使用引用計數, 所以有迴圈計數的問題. 為了打破迴圈,可以使用std
::weak_ptr. 顧名思義, weak_ptr是一個弱引用, 只引用, 不計數. 如果一塊記憶體被shared_ptr和weak_ptr同時引用, 當所有shared_ptr析構了之後,不管還有沒有weak_ptr引用該記憶體, 記憶體也會被釋放. 所以weak_ptr不保證它指向的記憶體一定是有效的, 在使用之前需要檢查.std::shared_ptr<int> p1(new int(5));std::weak_ptr<int> wp1 = p1; // 還是隻有p1有所有權. {  std::shared_ptr<int> p2 = wp1.lock(); // p1和p2都有所有權
  if(p2) // 使用前需要檢查  {     // 使用p2  }} // p2析構了, 現在只有p1有所有權. p1.reset(); // 記憶體被釋放. std::shared_ptr<int> p3 = wp1.lock(); // 因為記憶體已經被釋放了, 所以得到的是空指標.if(p3){  // 不會執行到這.}

shared_ptr的成員方法,user_count()的作用是獲得當前物件被引用的次數,reset()的作用是釋放指標對物件的引用,將指標設為空。
shared_ptr的執行緒安全性:
它是這樣說的: 

Boost 文件對於 shared_ptr 的執行緒安全有一段專門的記述,內容如下:
shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneosly by multiple threads (even when these instances are copies, and share the same reference count underneath.)
Any other simultaneous accesses result in undefined behavior.
翻譯為中文如下:
shared_ptr 物件提供與內建型別一樣的執行緒安全級別。一個 shared_ptr 例項可以同時被多個執行緒“讀”(僅使用不變操作進行訪問)。 不同的 shared_ptr 例項可以同時被多個執行緒“寫入”(使用類似 operator= 或 reset 這樣的可變操作進行訪問)(即使這些實 例是拷貝,而且共享下層的引用計數)。
任何其它的同時訪問的結果會導致未定義行為。”

這幾句話比較繁瑣,我總結一下它的意思:

1 同一個shared_ptr被多個執行緒“讀”是安全的。

2 同一個shared_ptr被多個執行緒“寫”是不安全的。

3 共享引用計數的不同的shared_ptr被多個執行緒”寫“ 是安全的。

如何印證上面的觀點呢?

其實第一點我覺得比較多餘。因為在多個執行緒中讀同一個物件,在正常情況下不會有什麼問題。

所以問題就是:如何寫程式證明同一個shared_ptr被多個執行緒"寫"是不安全的?

我的思路是,在多個執行緒中同時對一個shared_ptr迴圈執行兩遍swap。 shared_ptr的swap函式的作用就是和另外一個shared_ptr交換引用物件和引用計數,是寫操作。執行兩遍swap之後, shared_ptr引用的物件的值應該不變。

程式如下:

#include <stdio.h>#include <tr1/memory>#include <pthread.h>using std::tr1::shared_ptr;shared_ptr<int> gp(new int(2000));shared_ptr<int>  CostaSwapSharedPtr1(shared_ptr<int> & p){    shared_ptr<int> p1(p);    shared_ptr<int> p2(new int(1000));    p1.swap(p2);    p2.swap(p1);    return p1;}shared_ptr<int>  CostaSwapSharedPtr2(shared_ptr<int> & p){    shared_ptr<int> p2(new int(1000));    p.swap(p2);    p2.swap(p);    return p;}void* thread_start(void * arg){    int i =0;    for(;i<100000;i++)    {        shared_ptr<int> p= CostaSwapSharedPtr2(gp);        if(*p!=2000)        {            printf("Thread error. *gp=%d \n", *gp);            break;        }    }    printf("Thread quit \n");    return 0;}int main(){    pthread_t thread;    int thread_num = 10, i=0;    pthread_t* threads = new pthread_t[thread_num];    for(;i<thread_num;i++)        pthread_create(&threads[i], 0 , thread_start , &i);    for(i=0;i<thread_num;i++)        pthread_join(threads[i],0);    delete[] threads;    return 0;}

這個程式中我啟了10個執行緒。每個執行緒呼叫10萬次 CostaSwapSharedPtr2函式。 在CostaSwapSharePtr2函式中,對同一個share_ptr全域性變數gp進行兩次swap(寫操作), 在函式返回之後檢查gp的值是否被修改。如果gp值被修改,則證明多執行緒對同一個share_ptr執行寫操作是不安全的。

程式執行的結果如下:


Thread error. *gp=1000 Thread error. *gp=1000 Thread quit Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread error. *gp=1000 Thread quit Thread quit

10個執行緒有9個出錯。證明多執行緒對同一個share_ptr執行寫操作是不安全的。
我們在程式中,如果不執行CostaSwapSharedPtr2, 改成執行CostaSwapSharedPtr1呢?
  CostaSwapSharedPtr1和CostaSwapSharedPtr2的區別在於, 它不是直接對全域性變數gp進行寫操作,而是將gp拷貝出來一份再進行寫操作。執行的結果如下:
[email protected]:~/test/cpp/shared_ptr$ ./bThread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit Thread quit


           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述