C C 和指標 auto ptr智慧型指標

2021-08-27 02:33:33 字數 2813 閱讀 8032

一,建構函式與析構函式

auto_ptr在構造時獲取對某個物件的所有權(ownership),在析構時釋放該物件。我們可以這樣使用auto_ptr來提高**安全性:

int* p = new int(0);

auto_ptrap(p);

從此我們不必關心應該何時釋放p, 也不用擔心發生異常會有記憶體洩漏。

這裡我們有幾點要注意

1) 因為auto_ptr析構的時候肯定會刪除他所擁有的那個物件,所有我們就要注意了,乙個蘿蔔乙個坑,兩個auto_ptr不能同時擁有同乙個物件。像這樣:

int* p = new int(0);

auto_ptrap1(p);

auto_ptrap2(p);

因為ap1與ap2都認為指標p是歸它管的,在析構時都試圖刪除p, 兩次刪除同乙個物件的行為在c++標準中是未定義的。所以我們必須防止這樣使用auto_ptr.

2) 不應該用auto_ptr來管理乙個陣列指標:

int* pa = new int[10];

auto_ptrap(pa);

因為auto_ptr的析構函式中刪除指標用的是delete,而不是delete ,所以我們不應該用auto_ptr來管理乙個陣列指標。

4) 因為c++保證刪除乙個空指標是安全的, 所以我們沒有必要把析構函式寫成:

~auto_ptr() throw()

二,拷貝構造與賦值

與引用計數型智慧型指標不同的,auto_ptr要求其對「裸」指標的完全占有性。也就是說乙個」裸「指標不能同時被兩個以上的auto_ptr所擁有。那麼,在拷貝構造或賦值操作時,我們必須作特殊的處理來保證這個特性。auto_ptr的做法是「所有權轉移」,即拷貝或賦值的源物件將失去對「裸」指標的所有權,所以,與一般拷貝建構函式,賦值函式不同, auto_ptr的拷貝建構函式,賦值函式的引數為引用而不是常引用(const reference).當然,乙個auto_ptr也不能同時擁有兩個以上的「裸」指標,所以,拷貝或賦值的目標物件將先釋放其原來所擁有的物件

這裡的注意點是:

1) 因為乙個auto_ptr被拷貝或被賦值後, 其已經失去對原物件的所有權,這個時候,對這個auto_ptr的提領(dereference)操作是不安全的。如下:

int* p = new int(0);

auto_ptrap1(p);

auto_ptrap2 = ap1;

cout<<*ap1; //錯誤,此時ap1只剩乙個null指標在手了

2)將auto_ptr作為函式引數按值傳遞

因為在函式呼叫過程中在函式的作用域中會產生乙個區域性物件來接收傳入的auto_ptr(拷貝構造),這樣,傳入的實參auto_ptr就失去了其對原物件的所有權,而該物件會在函式退出時被區域性auto_ptr刪除。如下:

void f(auto_ptrap)

auto_ptrap1(new int(0));

f(ap1);

cout<<*ap1; //錯誤,經過f(ap1)函式呼叫,ap1已經不再擁有任何物件了。

【注意】因為這種情況太隱蔽,太容易出錯了, 所以auto_ptr作為函式引數按值傳遞是一定要避免的。或許大家會想到用auto_ptr的指標或引用作為函式引數或許可以,但是仔細想想,我們並不知道在函式中對傳入的auto_ptr做了什麼, 如果當中某些操作使其失去了對物件的所有權, 那麼這還是可能會導致致命的執行期錯誤。 也許,用const reference的形式來傳遞auto_ptr會是乙個不錯的選擇。

3)我們可以看到拷貝建構函式與賦值函式都提供了乙個成員模板在不覆蓋「正統」版本的情況下實現auto_ptr的隱式轉換。如我們有以下兩個類

class base{};

class derived: public base{};

那麼下列**就可以通過,實現從auto_ptr到auto_ptr的隱式轉換,因為derived*可以轉換成base*型別

auto_ptrapbase = auto_ptr(new derived);

4) 因為auto_ptr不具有值語義(value semantic), 所以auto_ptr不能被用在stl標準容器中。

所謂值語義,是指符合以下條件的型別(假設有類a):

a a1;

a a2(a1);

a a3;

a3 = a1;

那麼a2 == a1, a3 == a1

很明顯,auto_ptr不符合上述條件,而我們知道stl標準容器要用到大量的拷貝賦值操作,並且假設其操作的型別必須符合以上條件。

三,提領操作(dereference)

提領操作有兩個操作,乙個是返回其所擁有的物件的引用, 另乙個是則實現了通過auto_ptr呼叫其所擁有的物件的成員。如:

struct a

auto_ptrapa(new a);

(*apa).f();

apa->f();

當然, 我們首先要確保這個智慧型指標確實擁有某個物件,否則,這個操作的行為即對空指標的提領是未定義的。

四,輔助函式

1) get用來顯式的返回auto_ptr所擁有的物件指標。我們可以發現,標準庫提供的auto_ptr既不提供從「裸」指標到auto_ptr的隱式轉換(建構函式為explicit),也不提供從auto_ptr到「裸」指標的隱式轉換,從使用上來講可能不那麼的靈活, 考慮到其所帶來的安全性還是值得的。

2) release 用來轉移所有權

3) reset,用來接收所有權,如果接收所有權的auto_ptr如果已經擁有某物件, 必須先釋放該物件。

可見,auto_ptr短短百來行的**,還是包含了不少"玄機"的。

auto ptr智慧型指標

1 class auto ptr 這個智慧型指標應該保證,無論在何種情形下,只要自己被摧毀,就一定連帶釋放其所指資源。而由於智慧型指標本身就是區域變數,所以無論是正常退出,還是異常退出,只要函式退出,它就一定會被銷毀。注意 auto ptr不允許使用一般指標慣用的賦值 assign 初始化方式。必須...

智慧型指標 AutoPtr

include include include using namespace std void func autoptr 析構函式來負責釋放 void test catch exception e autoptr 析構函式來負責釋放 private t ptr struct aa void fun...

stl智慧型指標auto ptr

感覺auto ptr還是存在一些不足的,效率十分低,而且丟失了一般指標方便常用的操作,如 等,auto ptr只過載了 這幾個操作符,所以使用很不方便。一 說明 int a null delete a do nothing 應此auto ptr的析構函式是這樣子的 auto ptr 二 auto p...