c++中智能指針auto_ptr的簡介以及使用方法

本文介紹了智能指針auto_ptr的基本概念和簡單的使用方法,以及示例程序。然後根據智能指針的使用特點,自己定義了一個智能指針的模板類。以加深對智能指針的理解。

auto_ptr保證在異常被拋出時,分配的對象能夠自動消費,內存能夠自動釋放。使用auto_ptr可以代替指針進行操作,並且不關心內存的釋放。解決內存溢出的問題。

下面的程序包括auto_ptr一個簡單的示例一級自定義的一個類模板smart_pointer,以便鏈接智能指針的底層實現的原理: 

測試源代碼

#include "stdafx.h"
#include <iostream>
#include <string>
#include <memory>
#pragma warning(disable:4996)
using namespace std;

class test{
public:
	char *name;
	test(){
		cout << "constructor have not arg" << endl;
		name = NULL;
	}
	test(const char* str_name)
	{
		cout << "constructor have arg" << endl;
		name = new char[strlen(str_name) + 1];
		strcpy(name, str_name);
	}
	test& operator = (const char *str_name)
	{
		cout << "= overload" <<endl;
		if (NULL != name)
			delete name;
		name = new char[strlen(str_name) + 1];
		strcpy(name, str_name);
		return *this;
	}

	void show_name(void)
	{
		cout << "name:" << name << endl;
	}

	~test()
	{
		if (NULL != name)
			delete name;
		name = NULL;
		cout << "this ~test is called" << endl;
	}
};

//以下實現智能指針的類模板
template<typename T> class smart_pointer{
public:
	smart_pointer(T*p = 0);
	smart_pointer(const smart_pointer&ptr);
	smart_pointer& operator = (const smart_pointer&arg);
	T* operator -> ();
	T& operator * ();
	~smart_pointer();
private:
	void de_count(void)
	{
		if (--*count == 0)
		{
			delete c_ptr;
			delete count;
		}
	}
	T *c_ptr;//對象的指針
	int *count;//引用計數
};

template<typename T> smart_pointer<T>::smart_pointer(T *p)
{
	c_ptr = p;//c_ptr和p指向同一個內存
	count = new int(1);//初始值是1
}

template<typename T> smart_pointer<T>::smart_pointer(const smart_pointer<T> &ptr)
{
	c_ptr = ptr.c_ptr;
	count++;
	count = ptr.count;
}

template<typename T> smart_pointer<T>::~smart_pointer()
{
	de_count();//自身引用計數減一,如果減一後的引用計數爲0,那麼釋放內存
	cout << "destructor " << endl;
}

template<typename T> smart_pointer<T>& smart_pointer<T>::operator = (const smart_pointer<T> &ptr)
{
	++*ptr.count;
	de_count();
	c_ptr = ptr.c_ptr;
	count = ptr.count;

	return *this;
}

template<typename T> T* smart_pointer<T>::operator -> ()
{
	if (c_ptr)
		return c_ptr;
	//如果c_ptr爲空,拋出異常
	throw runtime_error("-> access NULL pointer");
}

template<typename T> T& smart_pointer<T>::operator *()
{
	if (c_ptr)
		return *c_ptr;
	//如果c_ptr爲空,拋出異常
	throw runtime_error("* access NULL pointer");
}

int main(int argc, char *argv[])
{
	//以下是使用std中標準的智能指針auto_ptr
	cout << "follow code is auto_ptr:" << endl;
	auto_ptr<test> ap_test1(new test("xyz"));//調用test類中的帶有參數的夠着函數,對name成員賦值
	auto_ptr<test> ap_test2(new test("abc"));
	//auto_ptr<test> ap_test3 = new test("xyzw");//這裏報錯,不能使用這種方式對智能指針賦值

	ap_test1->show_name();
	ap_test2->show_name();//顯示出當前name

	*ap_test1 = "apple";//調用重載運行算符=

	*ap_test2 = "banana";

	ap_test1->show_name();
	ap_test2->show_name();

#if 0
	/*以下的代碼的目的是讓程序執行異常,驗證智能指針會在程序異常的時候制動釋放所指向的內存*/
	int x = 1;
	int y = 0;
	cout << "follow will exception" << endl;
	throw runtime_error("this access NULL pointer");
	//x = x / y;
#endif

	//以下的代碼使用的是自己實現的智能指針類模板smart_pointer
	cout << endl;
	cout << endl;
	cout << "follow code is smart_pointer:" << endl;
	smart_pointer<test> st1;
	smart_pointer<test> st2(new test("pear"));
	smart_pointer<test> st3(new test("orange"));

	try{
		st1->show_name();
	}
	catch (const exception &err)
	{
		cout << err.what() << endl;
	}

	st2->show_name();
	*st2 = "apple";
	st2->show_name();
	st3->show_name();

	st2 = st3;//調用運算符=重載原來的st2的對象引用爲0,發生析構,st3的對象+1
	st2->show_name();


	return 0;

}

測試結果:

follow code is auto_ptr:
constructor have arg
constructor have arg
name:xyz
name:abc
= overload
= overload
name:apple
name:banana


follow code is smart_pointer:
constructor have arg
constructor have arg
-> access NULL pointer
name:pear
= overload
name:apple
name:orange
this ~test is called
name:orange
destructor
this ~test is called
destructor
destructor
this ~test is called
this ~test is called
請按任意鍵繼續. . .

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章