总体思路
使用类模板来实现多类型支持
构造函数(动态创建)、析构函数(销毁对象)
拷贝构造函数
拷贝运算符(->、*)
实现移动构造和移动运算符
对于引用计数的操作服从智能指针的设计规则
整体框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| template<class T> class new_shared_ptr { public: new_shared_ptr(); new_shared_ptr(const new_shared_ptr& p); ~new_shared_ptr(); new_shared_ptr& operator=(const new_shared_ptr<T>& obj); new_shared_ptr(new_shared_ptr&& dying_obj); new_shared_ptr& operator=(new_shared_ptr&& dying_obj);
int operator->();
int operator*(); private: T* ptr; int* ref_count; mutex *m_pMutex; }
|
构造函数
1
| new_shared_ptr(): ptr(new T), ref_count(new int(1)), mutex(new mutex) {}
|
拷贝构造函数
1 2 3 4 5 6 7 8 9 10 11 12 13
| new_shared_ptr(const new_shared_ptr& p) { ptr = p.ptr; ref_count = p.ref_count; mutex = p.mutex; if (p.ptr != nullptr) { m_pMutex->lock(); (*ref_count)++; m_pMutex->unlock(); } }
|
重载=、->、* 运算符
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
| new_shared_ptr& operator=(const new_shared_ptr<T>& obj) { if (obj.ptr == ptr) return *this; if (ptr) { m_pMutex->lock(); (*ref_count)--; m_pMutex->unlock(); if (*ref_count == 0) { delete ptr; delete ref_count; delete m_pMutex; } ptr = obj.ptr; ref_count = obj.ref_count; m_pMutex = obj.m_pMutex; m_pMutex->lock(); (*ref_count)++; m_pMutex->unlock(); } return *this; } T* operator->() return ptr; T& operator*() return *ptr;
|
移动构造
当使用移动构造函数创建一个新的智能指针并将另一个智能指针的资源所有权转移给它时,移动构造不会影响引用计数。引用计数会在资源所有权转移后保持不变,原来的智能指针会被置为 nullptr ,不再指向资源。这确保资源的唯一所有权。
1 2 3 4 5 6 7 8 9 10
| new_shared_ptr(new_shared_ptr&& dying_obj) : ptr(nullptr), ref_count(nullptr) { dying_obj.swap(*this); }
void swap(new_shared_ptr& other) { std::swap(ptr, other.ptr); std::swap(ref_count, other.ref_count); }
|
移动赋值
当使用移动赋值运算符将一个智能指针的资源所有权转移给另一个智能指针时,移动赋值不会影响引用计数。与移动构造类似,资源的所有权转移后,原来的智能指针会被置为 nullptr ,引用计数保持不变。
1 2 3 4 5 6
| new_shared_ptr& operator=(new_shared_ptr&& dying_obj) { new_shared_ptr(std::move(dying_obj)).swap(*this); return *this; }
|
析构函数
1 2 3 4 5 6 7 8 9 10 11
| ~new_shared_ptr() { if (!ptr || (*ref_count == 1)) { delete ptr; delete m_pMutex; delete ref_count; } else { m_pMutex->lock(); (*ref_count)--; m_pMutex->unlock(); } }
|
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 106
| #include <iostream> using namespace std;
class Type { public: int a = 1; };
class share_count { public: share_count() : _count(1) {}
void add_count() { ++_count; }
long reduce_count() { return --_count; }
long get_count() const { return _count; }
private: long _count; };
template<typename T> class smart_ptr { public: smart_ptr(T* ptr = NULL) : m_ptr(ptr), m_share_count(nullptr) { if (ptr) { m_share_count = new share_count; } }
~smart_ptr() { if (m_ptr && m_share_count && m_share_count->reduce_count() == 0) { delete m_ptr; delete m_share_count; cout << "~smart_ptr" << endl; } }
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
operator bool() const { return m_ptr != nullptr; }
smart_ptr(const smart_ptr& rhs) noexcept { m_ptr = rhs.m_ptr; m_share_count = rhs.m_share_count; if (m_ptr) { m_share_count->add_count(); } }
smart_ptr& operator=(const smart_ptr& rhs) noexcept { if (this != &rhs) { if (m_ptr && m_share_count && m_share_count->reduce_count() == 0) { delete m_ptr; delete m_share_count; } m_ptr = rhs.m_ptr; m_share_count = rhs.m_share_count; if (m_ptr) { m_share_count->add_count(); } } return *this; }
long use_count() const { if (m_ptr && m_share_count) { return m_share_count->get_count(); } return 0; }
private: T* m_ptr; share_count* m_share_count; };
|