C 智慧型指標

2021-10-01 04:26:47 字數 3729 閱讀 3769

大家都知道c/c++中對記憶體進行動態申請的時候, 堆上開闢的空間一定要進行釋放, 否則造成了記憶體洩漏是一件十分危險的事情, 但是我們在平時寫**的時候, 難免會忘記釋放空間, 或者當程式丟擲異常的時候, 釋放空間的**被跳過, 執行到, 這都是造成記憶體洩漏的原因. 為了解決這一情況, c++中引入了智慧型指標,來對動態開闢的記憶體進行管理.

raii的思想是指,利用物件的生命週期來對程式的資源進行管理, 即對乙個泛型的指標進行封裝, 以乙個物件的身份來管理動態開闢的空間, 而不單單是乙個指標的身份.

當我們要進行動態記憶體的開闢是, 可以建立乙個只能指標的物件, **在該物件的建構函式中進行空間的申請, 在物件的析構函式中進行空間的釋放.**這樣不僅解決了不需要使用者手動釋放空間的問題, 還保證了, 資源在物件的生命週期內始終有效.

接下來實現乙個簡單的實現raii思想的指標

template

<

class

t>

class

autoptr

~autoptr()

cout<<

"~autoptr()"

<

}private

: t* _ptr;};

void

fun(

)int

main()

catch

(const exception& e)

catch(.

..)return0;

}

上述程式中, 由於vector的開闢長度太長, 當層序執行到此處是,就會丟擲異常, 程式就會轉調到main程式中的捕獲異常出, 但是fun函式中的對p指標的釋放就沒有執行到, 這樣就造成了記憶體洩漏.

我們將fun函式改為如下程式

void

fun(

)

此時即使我們的fun函式中丟擲異常, 但是當程式跳轉到main函式中的時候, 也就是fun函式生命週期結束的時候, 會呼叫p物件的析構, 從而對空間進行釋放.

注意 : 只能指標在進行使用時, 必須保證開闢空間與常見物件在同一步進行,new操作符返回的是乙個指標型別, 因此直接在物件的構造中使用new操作符

當然, 只能指標的實現,還包括了指標的功能

template

<

class

t>

class

autoptr

~autoptr()

cout<<

"~autoptr()"

<

} t&

operator*(

) t*

operator

->()

private

: t* _ptr;

};

int

main()

注意 : 既然只能實現指標的基本操作,那麼就也有指標的拷貝與賦值操作, 指標的拷貝呼叫的是類的預設拷貝構造, 而預設拷貝構造只是乙個淺拷貝, 淺拷貝只拷貝值, 不會拷貝物件中的空間, 因此在執行上述**後,就會造成兩個指標指向同一塊空間, 這樣當main函式的生命週期執行完之後, 在對 p ,p1進行洗後的時候, 會對同一塊空間釋放兩次, 這樣回導致程式的崩潰

在stl中的auto_ptr是最早的一款智慧型指標, 它對指標的拷貝問題的解決是, 永遠保證只有乙個智慧型指標指向乙個空間, 當對當前智慧型指標進行拷貝的時候, 就將原來的指標置空.

在上述的 autoptr中對建構函式與賦值運算子過載進行修改

template

<

class

t>

class

autoptr

~autoptr()

cout<<

"~autoptr()"

<

}autoptr

(autoptr

& p)

autoptr

&operator

=(autoptr

& p)

_ptr=p._ptr;

p._ptr=

nullptr;}

} t&

operator*(

) t*

operator

->()

private

: t* _ptr;

};

注意 : 由於auto_ptr只能有乙個智慧型指標指向空間, 因此auto_ptr是乙個不完善的智慧型指標, 因此禁止使用

由於auto_ptr的不完備性, 容易造成空間的二次釋放, 因此c++11中有提供了乙個unique_ptr, 他處理問題的方法很簡單, 直接將拷貝構造與賦值運算子過載封死, 就最簡單的解決了問題.

template

<

class

t>

class

uniqueptr

~uniqueptr()

cout<<

"~autoptr()"

<

} t&

operator*(

) t*

operator

->()

uniqueptr

(autoptr&)

=delete

;operator

=(autoptr&)

=delete

;private

: t* _ptr;

};

在c++11中還有乙個更加全面的智慧型指標 sheard_ptr 它實現了前面倆個智慧型指標不能實現的拷貝與賦值.

它的原理是, 在智慧型指標的內部增加乙個計數器, 當有多個智慧型指標指向一塊空間是, 計數器就會加一, 當執行指正物件執行析構的時候, 先對計數器進行減一操作, 之後在判斷計數器的結果是否為零, 如果為零,則對空間進行釋放, 不為零則不作操作.

template

<

class

t>

class

sharedptr

~sharedptr()

}shareptr

(shareptr

& p)

;_ptr

(p._ptr)

,_count

(p._count)

shareptr

&operator

=(shareptr

& p)

_ptr=p._ptr;

_count=p._count;}(

*_count)++;

} t&

operator*(

) t*

operator

->()

intgitcount()

private

: t* _ptr;

int* _count;

};

注意:在shared_ptr的賦值運算子操作中, 賦值操作是將乙個指標替換成另乙個, 所以是要對指標記性判空, 刪除原來的值,在進行賦值, 而在shared_ptr中, 就需要先判斷_count的值是否是0 如果是0 則delete 之後賦值, 如果不是, 則直接改變智慧型指標內部的成員的值即

c 智慧型指標

auto prt 它是 它所指向物件的擁有者 所以當自身物件被摧毀時候,該物件也將遭受摧毀,要求乙個物件只有乙個擁有者,注意 auto prt 不能使用new 來分配物件給他 include include using namespace std template void bad print au...

c 智慧型指標

很久沒寫部落格了,不知道如何表達了,哈哈.我先介紹一下深淺拷貝.class copy 此時a.ptr和b.ptr指向同乙個物件,當我們delete a.ptr時 b.ptr所指向的物件已經不存在了,要是我們引用b.ptr指向的物件也就會出問題了.深拷貝 把a.ptr所指向的物件拷貝乙份給b.ptr ...

c 智慧型指標

記得前不久有一次面試被問到智慧型指標的實現,當時對智慧型指標只是聽說但沒有了解過,就亂七八糟地說了一遍。今天寫了一遍智慧型指標,用了引用計數的概念。主要思想就是,用乙個新類對原本需要的型別進行了一層封裝,這個新類中儲存了原本的物件指標和乙個引用計數的指標,之所以全部用指標來儲存,就是因為會出現多個新...