本文介紹了智能指針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
請按任意鍵繼續. . .