【C++】智能指針簡述(四):shared_ptr

  在開始本文內容以前,咱們再來總結一下,前文內容:函數

  1.智能指針採用RAII機制,在構造對象時進行資源的初始化,析構對象時進行資源的清理及汕尾.this

  2.auto_ptr防止拷貝後析構釋放同一塊內存,採用"轉移全部權"的方法.(實際開發中auto_ptr並不實用)spa

  3.scoped_ptr與auto_ptr相似,可是它與auto_ptr最大的區別是:它不能轉移全部權,即就是禁止拷貝/賦值!(固然,咱們也探討了C++中禁止拷貝對象的技術,在此不贅述)指針

  回顧完前文內容後,咱們今天來討論shared_ptr.code

  咱們雖然有了scoped_ptr,但在實際開發過程當中,咱們的確要是想對智能指針進行拷貝,那scoped_ptr就鞭長莫及了.對象

  那麼,咱們回到原始的問題:對智能指針進行拷貝,會出現什麼狀況?內存

  咱們在第二篇文章也分析了:若是對智能指針不進行特殊處理,在析構時,會將同一塊內存釋放屢次,程序會崩潰!ci

  所以,咱們要想對智能指針進行拷貝,就必須作一些特殊的處理,使得析構函數只釋放一次內存.資源

  此時,若是探究過深淺拷貝的同窗,可能心中已經有了答案:用引用計數!!!(深淺拷貝問題,之後我會討論,不是本文重點)開發

  考慮到有些童鞋可能不知道什麼是引用計數,那我就在這裏解釋一下:

  在引用計數中,每個對象負責維護對象全部引用的計數值。當一個新的引用指向對象時,引用計數器就遞增,當去掉一個引用時,引用計數就遞減。當引用計數到零時,該對象就將釋放佔有的資源。——百度百科

  通俗一點的講:在本例中咱們經過count變量來記錄當前有多少個對象共同維護着這個指針,每次拷貝/賦值的時候,讓count++.

1

2

3

4

5

6

7

8

//拷貝構造(賦值運算符重載相似,用簡潔寫法調用拷貝構造便可)

SharedPtr(const SharedPtr &sp)

    :_ptr(sp._ptr)

    ,_count(sp._count){

        if(_count!=NULL){

            ++(*_count);

        }

}

  當對象析構時,首先咱們看count是否是1,若是不是1,說明還有其餘對象在維護這個指針,咱們讓count--.不然的話,就說明,只有當前對象在維護這個指針,此時就能夠愉快的把指針delete掉了.

1

2

3

4

5

6

7

8

9

10

~SharedPtr(){

    if(count!=NULL && *count == 1){

        delete _ptr;

        delete _count;

        _ptr = NULL;

        _count = NULL;

    }else{

        --(*count);

    }

}

  經過這樣的的形式,就能夠保證:在多個shared_ptr對象共同維護一塊內存中,對內存只delete一次.

  最終,貼上我簡化後shared_ptr的代碼.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

/*

*文件說明:模擬實現shared_ptr

*做者:高小調

*日期:2017-03-31

*集成開發環境:Microsoft Visual Studio 2010

*/

#pragma once

template<typename T>

class SharedPtr{

public:

    //構造函數

    SharedPtr(T *ptr=NULL)

        :_ptr(ptr)

        ,_count(NULL){

            if(ptr!=NULL){

                _count = new int(1);

                std::cout<<_ptr<<" Is Created"<<std::endl;

            }

    }

    //拷貝構造

    SharedPtr(const SharedPtr & sp)

        :_ptr(sp._ptr)

        ,_count(sp._count){

            if(sp._count!=NULL){

                ++(*_count);

            }

    }

    //賦值運算符重載

    SharedPtr& operator=(const SharedPtr &sp){

        if(_ptr!=sp._ptr){

            SharedPtr tmp(sp);

            std::swap(_ptr,tmp._ptr);

            std::swap(_count,tmp._count);

        }

        return *this;

    }

    //析構函數

    ~SharedPtr(){

        if(_count!=NULL && --(*_count)==0){

            std::cout<<_ptr<<" Is Destory"<<std::endl;

            delete _ptr;

            delete _count;

            _ptr = NULL;

            _count = NULL;

        }

    }

private:

    T* _ptr;

    int *_count;

};

 

void TestSharedPtr(){

    SharedPtr<int> sp1(new int(10));

    SharedPtr<int> sp2(new int(20));

    SharedPtr<int> sp3(new int(30));

    SharedPtr<int> sp4(sp1);

    sp2 = sp1;

    sp3 = sp1;

}

相關文章
相關標籤/搜索