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	}


更多相关文章

  1. Linux 下 Sublime Text 3 安装 Godef 进行代码跳转/跳回
  2. Linux 上传代码到github
  3. linux 下使用 vim+cscope+ctags+taglist+NERDtree实现代码阅读编
  4. 如何查看linux命令源代码和函数源代码
  5. UNIX网络编程之源代码的编译和使用
  6. mt7620的u-boot 代码
  7. 在arcpy中删除或删除表的代码是什么?
  8. iBatis中sqlmap resultclass="java.lang.Integer",在代码中如何
  9. 已有SQLSERVER表如何生成其代码?

随机推荐

  1. MediaScannerReceiver
  2. 2011.07.18——— android AlphaBitmap
  3. android:gravity的值可以使用|连接多个属
  4. Android——AppWidgetProvider应用
  5. Android获取当前WiFi的MAC地址-适配所有
  6. Android 中ListView的应用
  7. Android休眠唤醒机制简介(一)
  8. Android屏幕横屏竖屏设置技巧
  9. intentDemo_2
  10. android activity 的 looper, Handler处