SMART POINTER(智慧指標) (轉)

themoney發表於2007-09-30
SMART POINTER(智慧指標) (轉)[@more@]

智慧指標(smart pointer):
智慧指標是其實是一個A,它帶有一個模針成員變數m_p.用該A管理m_p,透過這種管理機制,可以防止由於new而導致的洩漏.
智慧指標物件在使用時像指標一樣.同時也具有一般物件的所有特徵.如果要注意以下幾點:
1,物件之間的賦值:若有A=B,則在賦值時,
首先要松查是否為自身賦值.如果不是,則釋放A物件成員指標的記憶體空間,
然後要將B中的成員指標賦值於A的成員指標,
接著將B中的成員指標置為空,這樣可以避免多個指標同時指向一個記憶體空間而產生多次析構此記憶體空間的錯誤.
所以,過載的賦值一般如下:
operator =(Test& _); 此處不能為const 物件的引用,這是因為要修改source_object 的成員指標為空.
2,對於copy constroctor也有與operator=類似的情況.只不過不要釋放A成員指標的記憶體空間,.
3,關於member template的問題,它往往用於相容模板物件之間的相互賦值,copy constroctor.我們可以將它看成是個模板類(一個類).
譬如:auto_ptr,這就是一個類名稱
  另:VC7.0中,成員模板的定義和實現必須放在類的定義中.
注:member template不能為static 或virtual
4,智慧指標中必須過載的幾個運算子: ->  *
這樣做的目的就是將物件模仿成指標的行為.
如下:
T* operator ->() 
{return m_p;}

特別注意:
object->m_p;== (object.operator->())->m_p;


T& operator *()
{return *m_p;}


下面的演示smart pointer的基本使用:
#include"iostream"
using namespace std;
template
class auto_ptr
{
public:
 auto_ptr( T *p=0)
 {
 m_p=p;
 }

  //由auto_ptr 來複制構造該auto_ptr物件.
 auto_ptr(auto_ptr& source_object)
 {
  m_p=(T*)( source_object.get());

 source_object.m_p=0;  //

 }
 //由auto_ptr來構造該auto_ptr物件. 
 template
 auto_ptr(auto_ptr  &source_object)  //此處的物件為非const 物件的引用.
 {
  m_p=(T*)( source_object.get());
 source_object.m_p=0;  //
 }

 //析構....
 ~auto_ptr()
 {
 if (m_p!=0)
 Release();
 }

 //由auto_ptr賦值於auto_ptr物件.
  auto_ptr& operator=(auto_ptr &source_object)
 {
 Release();
  m_p=(T*)(source_object.get());
 return *this;
 }

  //由auto_ptr賦值於auto_ptr物件.
 template
 auto_ptr& operator=(auto_ptr &source_object)
 {
 Release();
  m_p=(T*)(source_object.get());
 return *this;
 }
 
  //delete m_p;
 void Release()
 {
 if (m_p!=0)
 delete m_p;
 m_p=0;
 }

 T* get()
 {
 return m_p;
 }
 // from auto_ptr convert to auto_ptr


 //宣告:1 由於上面提供從auto_ptr構造auto_ptr的建構函式.所以,在實際上,不必給出下面的隱式型別轉換函式.
 //  2 VC不支援這個隱式轉換特性.
 template
  operator auto_ptr() 
  //如果M和T型別不一致時,將無法進行自動的型別轉換.如:auto_ptr 與auto_ptr
 {
 
  return auto_ptr(m_p);

  //此處困惑:::
  // return auto_ptr(m_p); 這是more effective C++中的寫法,當此語句時,會構造出一個新auto_ptr的物件,而this物件的m_p並未釋放.這樣兩個物件的m_p指向共一個變數,???
  //應該這樣:
  //temp auto_ptr(get());
 //Release();
 //return temp;
 }

 T* operator ->()
 {
 return m_p; 
  }

 const T* operator->() const
 {
 return m_p;
 }
 //此處注意為T&,這樣可以實現左值.
 T& operator *()
 {
 return *m_p;
 }

 const T& operator *() const
 {
 return *m_p;
 }
public:
 T *m_p;
};


class test
{
public:
 test(int data)
 {
 m_data=data;
 }
int& operator->()
{
 return m_data;
}

  operator int()
{
 return m_data;
}

public:
 

 int m_data;
};

 

class A
{
public:
 A(int data)
 {
 m_data=data;
 }
private:
 int m_data;

};

class B:public A
{
public:
 B(int data):A(data*2),m_data(data)
 {
 ;
 }
private:
 int m_data;

};

class C:public A
{
public:
 C(int data):A(data*3),m_data(data)
 {
 ;
 }
private:
 int m_data;


};
void test_member_template(const auto_ptr& source_object) 
//此處一定要加const,因為物件隱式轉換後生成的物件為臨時物件.臨時物件的生存週期將不由程式設計師決定,其值不能被修改.
{
//source_object.get();
}

void test_member_template2(const auto_ptr& source_object)
//此處一定要加const,因為物件隱式轉換後生成的物件為臨時物件.臨時物件的生存週期將不由程式設計師決定,其值不能被修改.
{
 ;
}

void main()
{
 auto_ptr object2(new C(3));
 test_member_template(object2);
  //將member template constructor 構造出auto_ptr 物件.注意,函式執行後,將導致object2變為為空殼物件.要避免這種隱式的模板物件構造.

 auto_ptr object(new test(15));
 int data=object.operator->()->m_data;
 //等價於:  data=object.operator->()->operator->();
 cout<

  auto_ptr object_int(new int(999));

 auto_ptr object_int_2(new int(333));

 object_int_2=object_int; //operator =

 object_float=object_int; //operator =  by member template

 test_member_template2(object_int);  //copy constructor

  test_member_template2(object_float);//call constructor by member template.
  //注意,函式執行後,將導致object2變為為空殼物件.要避免這種隱式的模板物件構造.
 cout< auto_ptr object_2=object_float;
  //此處呼叫 copy constructor
 cout<

 
}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10794571/viewspace-974274/,如需轉載,請註明出處,否則將追究法律責任。

相關文章