C++智能指针的理解与实现

一、什么是智能指针

       由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见。用智能指针便可以有效缓解这类问题

引用《more effective c++》中的话:

所谓的智能指针,是看起来,用起来感觉都像是内建的指针,但提供更多功能的一种对象。

因此说:

智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。

二、常见的智能指针

1. std::auto_ptr

有很多问题。 不支持复制(拷贝构造函数)和赋值(operator =),但复制或赋值的时候不会提示出错,因为不能被复制,所以不能被放入容器中。

2. unique_ptr

也不支持复制和赋值,但比auto_ptr好,直接赋值会编译出错。实在想赋值的话,需要使用:std::move。

std::unique_ptr p1(new int(5)); 
std::unique_ptr p2 = p1; // 编译会出错 
std::unique_ptr p3 = std::move(p1); // 转移所有权, 现在那块内存归p3所有, p1成为无效的指针.

3. shared_ptr

基于引用计数的智能指针。可随意赋值,直到内存的引用计数为0的时候这个内存会被释放。

三、智能指针的实现与比较

下面是一个基于引用计数的智能指针的实现,需要实现构造,析构,拷贝构造,=操作符重载,重载*-和>操作符。

#include<iostream>
#include<memory>
using namespace std;
template <typename T>
class SmartPointer {
public:
    //构造函数  
    SmartPointer(T* p = 0) : _ptr(p), _reference_count(new size_t) {
        if (p)
            *_reference_count = 1;
        else
            *_reference_count = 0;
    }
    //拷贝构造函数  
    SmartPointer(const SmartPointer& src) {
        if (this != &src) {
            _ptr = src._ptr;
            _reference_count = src._reference_count;
            (*_reference_count)++;
        }
    }
    //重载赋值操作符  
    SmartPointer& operator=(const SmartPointer& src) {
        if (_ptr == src._ptr) {
            return *this;
        }
        releaseCount();
        _ptr = src._ptr;
        _reference_count = src._reference_count;
        (*_reference_count)++;
        return *this;
    }

    //重载操作符  
    T& operator*() {
        if (_ptr) {
            return *_ptr;
        }
        //throw exception  
    }
    //重载操作符  
    T* operator->() {
        if (_ptr) {
            return _ptr;
        }
        //throw exception  
    }
    //析构函数  
    ~SmartPointer() {
        if (--(*_reference_count) == 0) {
            delete _ptr;
            delete _reference_count;
        }
    }
private:
    T *_ptr;
    size_t *_reference_count;
    void releaseCount() {
        if (_ptr) {
            (*_reference_count)--;
            if ((*_reference_count) == 0) {
                delete _ptr;
                delete _reference_count;
            }
        }
    }
};
   
   
  • 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
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 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
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

建立一个对象用于检测:

class Simple {
public:
    Simple(int param = 0) {
        number = param;
        std::cout << "Simple: " << number << std::endl;
    }
    ~Simple() {
        std::cout << "~Simple: " << number << std::endl;
    }
    int number;
};
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

完整的运行测试代码:

#include<iostream>
#include<memory>
using namespace std;
template <typename T>
class SmartPointer {
public:
    //构造函数  
    SmartPointer(T* p = 0) : _ptr(p), _reference_count(new size_t) {
        if (p)
            *_reference_count = 1;
        else
            *_reference_count = 0;
    }
    //拷贝构造函数  
    SmartPointer(const SmartPointer& src) {
        if (this != &src) {
            _ptr = src._ptr;
            _reference_count = src._reference_count;
            (*_reference_count)++;
        }
    }
    //重载赋值操作符  
    SmartPointer& operator=(const SmartPointer& src) {
        if (_ptr == src._ptr) {
            return *this;
        }
        releaseCount();
        _ptr = src._ptr;
        _reference_count = src._reference_count;
        (*_reference_count)++;
        return *this;
    }

    //重载操作符  
    T& operator*() {
        if (_ptr) {
            return *_ptr;
        }
        //throw exception  
    }
    //重载操作符  
    T* operator->() {
        if (_ptr) {
            return _ptr;
        }
        //throw exception  
    }
    //析构函数  
    ~SmartPointer() {
        if (--(*_reference_count) == 0) {
            delete _ptr;
            delete _reference_count;
        }
    }
private:
    T *_ptr;
    size_t *_reference_count;
    void releaseCount() {
        if (_ptr) {
            (*_reference_count)--;
            if ((*_reference_count) == 0) {
                delete _ptr;
                delete _reference_count;
            }
        }
    }
};
class Simple {
public:
    Simple(int param = 0) {
        number = param;
        std::cout << "Simple: " << number << std::endl;
    }

    ~Simple() {
        std::cout << "~Simple: " << number << std::endl;
    }
    int number;
};
int main()
{
    SmartPointer<char> cp1(new char('a'));
    cout << *cp1 << endl;
    SmartPointer<char> cp2(cp1);
    cout << *cp2 << endl;
    SmartPointer<char> cp3;
    cp3 = cp2;
    cp3 = cp1;
    cp3 = cp3;
    SmartPointer<char> cp4(new char('b'));
    cp3 = cp4;
    cout << *cp3 << endl;
    //
    auto_ptr<Simple> autoPtr(new Simple(10));
    auto_ptr<Simple> autoPtr1;
    cout << autoPtr->number << endl;
    autoPtr1 = autoPtr;
    cout << autoPtr1->number << endl;
    cout << autoPtr->number << endl;
    SmartPointer<Simple>myPointer(new Simple(1));
    SmartPointer<Simple>myPointer1;
    myPointer1 = myPointer;
    cout<<myPointer1->number<<endl;
    cout << myPointer->number << endl;
}
   
   
  • 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
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 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
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

参考文章: 
《more effective c++》 
http://blog.csdn.net/xt_xiaotian/article/details/5714477 
http://blog.csdn.net/worldwindjp/article/details/18843087

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值