自己实现的C++智能指针的功能代码和测试用例
16lz
2021-01-22
1)C++,智能指针的相关知识请 wwww.baidu.com
2)智能指针有很多功能点,不同项目可能需要的智能指针的功能点不一样多,所以人人实现的C++智能指针可能是不一样的。但是:智能指针的最基本的功能点还是必须要遵守的。
3)今天趁着晚上的时间实现了C++ 智能指针的功能代码和测试用例,以下是实现代码。代码经过测试,可能编译通过和测试通过。代码中一定存在缺陷部分,请指出。
4)
注1:对于TRefHelper类中对引用计数器的加减操作,如果是在多线程环境中,就需要使用多线程安全的原子计数器完成引用计数的加减!多线程安全的原子计数器可以参考前面写的文章,"原子计数器 for PThreads",链接:http://blog.csdn.net/u012421852/article/details/51357176
注2:C++中对class进行new操作,不同的入参就会对应调用到class的正确的不同的构造函数,关于new和class构造函数的技术 在 ”只在堆上创建class对象“和”只在栈上创建class对象“会很好的体现,后面会用一篇文件实现new/delete知识点(”只在堆上创建class对象“和”只在栈上创建class对象“)的功能代码和测试用例。
#include <stdio.h> #include <assert.h> #include <string> #include <iostream> using namespace std; #define PRINT_FUN_INFO \ do { \ printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); \ }while(0); #define PRINT_REF_INFO \ do { \ printf("%s:%d:%s<objptr, objref>(%p, %d)\n", __FILE__, __LINE__, __FUNCTION__, m_ptr, m_ref);\ }while(0); class CDog { public: CDog(int age, std::string color):m_age(age), m_color(color) { cout<<"Hello one dog<age, color>("<<m_age<<","<<m_color<<")"<<endl; } ~CDog() { cout<<"Bye one dog<age, color>("<<m_age<<","<<m_color<<")"<<endl; } void Run() { printf("%s:%d:%s, dog(%p).\n", __FILE__, __LINE__, __FUNCTION__); } private: int m_age; std::string m_color; }; template<class T> class TRefHelper { template<class Y> friend class TSmart_Ptr; TRefHelper(T *ptr):m_ptr(ptr), m_ref(1) { PRINT_REF_INFO; } ~TRefHelper() { PRINT_REF_INFO; delete m_ptr; m_ptr = NULL; } void delRef() { PRINT_REF_INFO; --m_ref; } void addRef() { PRINT_REF_INFO; ++m_ref; } int getRef() const { return m_ref; } T* get() const { return m_ptr; } private: T* m_ptr; int m_ref; }; template<class T> class TSmart_Ptr { public: explicit TSmart_Ptr(T* ptr):m_helper(new TRefHelper<T>(ptr)) { PRINT_FUN_INFO; assert (ptr != NULL); } explicit TSmart_Ptr(TSmart_Ptr const& other):m_helper(other.m_helper) { PRINT_FUN_INFO; (other.m_helper)->addRef(); } ~TSmart_Ptr() { PRINT_FUN_INFO; m_helper->delRef(); if (m_helper->getRef() == 0) { delete m_helper; m_helper = NULL; } } TSmart_Ptr& operator=(TSmart_Ptr const& rhs) { PRINT_FUN_INFO; if (rhs.get() != get()) { (rhs.m_helper)->addRef(); (this->m_helper)->delRef(); if ((this->m_helper)->getRef() == 0) { delete m_helper; m_helper = NULL; } *this = rhs; } return *this; } T* get() const { PRINT_FUN_INFO; return m_helper->get(); } T* operator->() const { PRINT_FUN_INFO; T* ret = NULL; if (m_helper != NULL) { ret = m_helper->get(); } return ret; } T& operator*() const { PRINT_FUN_INFO; T* ret = NULL; if (m_helper != NULL) { ret = m_helper->get(); } return *ret; } bool operator!() const { PRINT_FUN_INFO; assert (m_helper != NULL); return m_helper->get() != NULL; } private: TRefHelper<T> *m_helper; }; int main() { PRINT_FUN_INFO CDog *dog = new CDog(25, "Red"); PRINT_FUN_INFO TSmart_Ptr<CDog> smart_ptr1(dog); PRINT_FUN_INFO TSmart_Ptr<CDog> smart_ptr2(smart_ptr1); PRINT_FUN_INFO smart_ptr2 = smart_ptr1; PRINT_FUN_INFO assert (smart_ptr2.get() != NULL); PRINT_FUN_INFO assert (!smart_ptr2); PRINT_FUN_INFO smart_ptr2.get()->Run(); PRINT_FUN_INFO smart_ptr2->Run(); PRINT_FUN_INFO (*smart_ptr2).Run(); PRINT_FUN_INFO return 0; }
可先只进行编译,进行代码调试:
$g++ -c ./SmartPtr.cpp -lstdc++
或者直接编译加链接:
$g++ ./SmartPtr.cpp -lstdc++
下面是运行结果:
./smartptr.cpp:149:main Hello one dog<age, color>(25,Red) ./smartptr.cpp:151:main ./smartptr.cpp:42:TRefHelper<objptr, objref>(0x8dee020, 1) ./smartptr.cpp:78:TSmart_Ptr ./smartptr.cpp:153:main ./smartptr.cpp:83:TSmart_Ptr ./smartptr.cpp:57:addRef<objptr, objref>(0x8dee020, 1) ./smartptr.cpp:155:main ./smartptr.cpp:98:operator= ./smartptr.cpp:114:get ./smartptr.cpp:114:get ./smartptr.cpp:157:main ./smartptr.cpp:114:get ./smartptr.cpp:159:main ./smartptr.cpp:139:operator! ./smartptr.cpp:161:main ./smartptr.cpp:114:get ./smartptr.cpp:30:Run, dog(0xbfa490e4). ./smartptr.cpp:163:main ./smartptr.cpp:119:operator-> ./smartptr.cpp:30:Run, dog(0xbfa490e4). ./smartptr.cpp:165:main ./smartptr.cpp:129:operator* ./smartptr.cpp:30:Run, dog(0xbfa490e4). ./smartptr.cpp:167:main ./smartptr.cpp:88:~TSmart_Ptr ./smartptr.cpp:52:delRef<objptr, objref>(0x8dee020, 2) ./smartptr.cpp:88:~TSmart_Ptr ./smartptr.cpp:52:delRef<objptr, objref>(0x8dee020, 1) ./smartptr.cpp:46:~TRefHelper<objptr, objref>(0x8dee020, 0) Bye one dog<age, color>(25,Red)
注:为了方便对比测试运行结果和源代码,附录附加上去加了行数的源代码。
1 #include <stdio.h> 2 #include <assert.h> 3 #include <string> 4 #include <iostream> 5 using namespace std; 6 7 #define PRINT_FUN_INFO \ 8 do { \ 9 printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); \ 10 }while(0); 11 12 #define PRINT_REF_INFO \ 13 do { \ 14 printf("%s:%d:%s<objptr, objref>(%p, %d)\n", __FILE__, __LINE__, __FUNCTION__, m_ptr, m_ref);\ 15 }while(0); 16 17 class CDog 18 { 19 public: 20 CDog(int age, std::string color):m_age(age), m_color(color) 21 { 22 cout<<"Hello one dog<age, color>("<<m_age<<","<<m_color<<")"<<endl; 23 } 24 ~CDog() 25 { 26 cout<<"Bye one dog<age, color>("<<m_age<<","<<m_color<<")"<<endl; 27 } 28 void Run() 29 { 30 printf("%s:%d:%s, dog(%p).\n", __FILE__, __LINE__, __FUNCTION__); 31 } 32 private: 33 int m_age; 34 std::string m_color; 35 }; 36 37 template<class T> class TRefHelper 38 { 39 template<class Y> friend class TSmart_Ptr; 40 TRefHelper(T *ptr):m_ptr(ptr), m_ref(1) 41 { 42 PRINT_REF_INFO; 43 } 44 ~TRefHelper() 45 { 46 PRINT_REF_INFO; 47 delete m_ptr; 48 m_ptr = NULL; 49 } 50 void delRef() 51 { 52 PRINT_REF_INFO; 53 --m_ref; 54 } 55 void addRef() 56 { 57 PRINT_REF_INFO; 58 ++m_ref; 59 } 60 int getRef() const 61 { 62 return m_ref; 63 } 64 T* get() const 65 { 66 return m_ptr; 67 } 68 private: 69 T* m_ptr; 70 int m_ref; 71 }; 72 73 template<class T> class TSmart_Ptr 74 { 75 public: 76 explicit TSmart_Ptr(T* ptr):m_helper(new TRefHelper<T>(ptr)) 77 { 78 PRINT_FUN_INFO; 79 assert (ptr != NULL); 80 } 81 explicit TSmart_Ptr(TSmart_Ptr const& other):m_helper(other.m_helper) 82 { 83 PRINT_FUN_INFO; 84 (other.m_helper)->addRef(); 85 } 86 ~TSmart_Ptr() 87 { 88 PRINT_FUN_INFO; 89 m_helper->delRef(); 90 if (m_helper->getRef() == 0) 91 { 92 delete m_helper; 93 m_helper = NULL; 94 } 95 } 96 TSmart_Ptr& operator=(TSmart_Ptr const& rhs) 97 { 98 PRINT_FUN_INFO; 99 if (rhs.get() != get()) 100 { 101 (rhs.m_helper)->addRef(); 102 (this->m_helper)->delRef(); 103 if ((this->m_helper)->getRef() == 0) 104 { 105 delete m_helper; 106 m_helper = NULL; 107 } 108 *this = rhs; 109 } 110 return *this; 111 } 112 T* get() const 113 { 114 PRINT_FUN_INFO; 115 return m_helper->get(); 116 } 117 T* operator->() const 118 { 119 PRINT_FUN_INFO; 120 T* ret = NULL; 121 if (m_helper != NULL) 122 { 123 ret = m_helper->get(); 124 } 125 return ret; 126 } 127 T& operator*() const 128 { 129 PRINT_FUN_INFO; 130 T* ret = NULL; 131 if (m_helper != NULL) 132 { 133 ret = m_helper->get(); 134 } 135 return *ret; 136 } 137 bool operator!() const 138 { 139 PRINT_FUN_INFO; 140 assert (m_helper != NULL); 141 return m_helper->get() != NULL; 142 } 143 private: 144 TRefHelper<T> *m_helper; 145 }; 146 147 int main() 148 { 149 PRINT_FUN_INFO 150 CDog *dog = new CDog(25, "Red"); 151 PRINT_FUN_INFO 152 TSmart_Ptr<CDog> smart_ptr1(dog); 153 PRINT_FUN_INFO 154 TSmart_Ptr<CDog> smart_ptr2(smart_ptr1); 155 PRINT_FUN_INFO 156 smart_ptr2 = smart_ptr1; 157 PRINT_FUN_INFO 158 assert (smart_ptr2.get() != NULL); 159 PRINT_FUN_INFO 160 assert (!smart_ptr2); 161 PRINT_FUN_INFO 162 smart_ptr2.get()->Run(); 163 PRINT_FUN_INFO 164 smart_ptr2->Run(); 165 PRINT_FUN_INFO 166 (*smart_ptr2).Run(); 167 PRINT_FUN_INFO 168 169 return 0; 170 }
更多相关文章
- Linux 下 Sublime Text 3 安装 Godef 进行代码跳转/跳回
- Linux 上传代码到github
- linux 下使用 vim+cscope+ctags+taglist+NERDtree实现代码阅读编
- 如何查看linux命令源代码和函数源代码
- UNIX网络编程之源代码的编译和使用
- mt7620的u-boot 代码
- 在arcpy中删除或删除表的代码是什么?
- iBatis中sqlmap resultclass="java.lang.Integer",在代码中如何
- 已有SQLSERVER表如何生成其代码?