c++中動態記憶體的管理主要是使用new/delete表示式和std::allcator類。為了管理動態記憶體更加安全,c++11新標準庫推出了智慧型指標。
new/delete
new完成的操作:
(1): 它分配足夠儲存乙個特定型別物件的記憶體
(2):為它剛才分配的記憶體中的那個物件設定初始值。(對於內建型別物件,就是預設初始化該它,對應類型別,呼叫constructor初始化)
delete完成的操作:
(1):銷毀給定指標指向的物件
(2):釋放該物件的對應記憶體
常見問題
1.申請的空間沒有進行釋放,會出現記憶體洩漏。這種忘記釋放的記憶體如果不退出程式將永遠不會歸還給系統。解決方法:
int
*p=new
int(0)
;delete p;
p=nullptr
;//釋放該指標後指向空,一可以避免再次訪問它出現未定義行為,二可以避免再次delete它出現未定義行為。
int
*pa;
delete pa;
2.使用已經釋放記憶體的物件解決方法:對已經釋放的記憶體物件賦給乙個空指標,在使用前判斷是否為空指標。
int
*p=new
int(0)
;delete p;
p=nullptr
;//也可=null/0
//......
if(p)
3.同一塊記憶體釋放兩次,雖然這個問題聽起來不太可能發生,但當有兩個指標指向同一塊記憶體時,可能就容易發生了。避免方法:delete後直接將記憶體物件置為空指標。
智慧型指標的使用及原理
什麼是智慧型指標?
智慧型指標是乙個類,這個類的建構函式中傳入乙個普通指標,析構函式中釋放傳入的指標。智慧型指標的類都是棧上的物件,所以當函式(或程式)結束時會自動被釋放,
rall
rall是一種利用物件生命週期來控制程式資源(如記憶體、檔案控制代碼、網路連線、互斥量等)的技術。
在物件構造時獲取資源,接著控制對資源的訪問使之在物件的生命週期內始終保持有效,最後在物件析構的時候釋放資源。藉此,我們實際上把管理乙份資源的責任託管給了乙個物件。這種做法有兩大好處:
智慧型指標的原理
raii特性
過載operator*和opertaor->,從而具有指標一樣的行為。
使用rall思想設計智慧型指標:
template
<
class
t>
class
smartptr
~smartptr()
t&operator*(
) t*
operator
->()
private
: t* _ptr;};
struct date
}
std::auto_ptr
auto_ptr的實現原理:管理權轉移/轉移資源的思想。在c++98中提供,盡量不要使用。
template
<
class
t>
class
autoptr
~autoptr()
autoptr
(autoptr
& ap)
:_ptr
(ap._ptr)
autoptr
&operator
=(autoptr
& ap)
return
*this;}
t&operator*(
) t*
operator
->()
private
: t* _ptr;
};
注意:
不要使用auto_ptr儲存乙個非動態開闢空間的指標,因為在作用域結束的時候,會執行智慧型指標的析構函式,釋放這塊空間,但非動態的空間又無法釋放;
不要使用兩個auto_ptr指標指向同乙個指標,因為會產生額外開銷;
不要使用auto_ptr指向乙個指標陣列,因為auto_ptr的析構函式所用的是delete而不是delete;
不要將auto_ptr儲存在容器中,因為賦值和拷貝構造後原指標無法使用。
std::unique_ptr
unique_ptr的實現原理:防拷貝,c++11中實現。
template
<
class
t>
class
uniqueptr
~uniqueptr()
t&operator*(
) t*
operator
->()
private
:// c++98防拷貝的方式:只宣告不實現+宣告成私有
uniqueptr
(uniqueptr
const&)
; uniqueptr &
operator
=(uniqueptr
const&)
;// c++11防拷貝的方式:delete
uniqueptr
(uniqueptr
const&)
=delete
; uniqueptr &
operator
=(uniqueptr
const&)
=delete
;private
: t * _ptr;
};
std::shared_ptr
shared_ptr的原理:是通過引用計數的方式來實現多個shared_ptr物件之間共享資源。
注意
shared_ptr在其內部,給每個資源都維護了著乙份計數,用來記錄該份資源被幾個物件共享。
在物件被銷毀時(也就是析構函式呼叫),就說明自己不使用該資源了,物件的引用計數減一。
如果引用計數是0,就說明自己是最後乙個使用該資源的物件,必須釋放該資源;
如果不是0,就說明除了自己還有其他物件在使用該份資源,不能釋放該資源,否則其他物件就成野指標了。
#include
#include
template
<
class
t>
class
sharedptr
~sharedptr()
sharedptr
(const sharedptr
& sp)
:_ptr
(sp._ptr)
,_prefcount
(sp._prefcount)
,_pmutex
(sp._pmutex)
// sp1 = sp2
sharedptr
&operator=(
const sharedptr
& sp)
return
*this;}
t&operator*(
) t*
operator
->()
intusecount()
t*get()
void
addrefcount()
private
:void
release()
_pmutex.
unlock()
;if(deleteflag ==
true
)delete _pmutex;
}private
:int
* _prefcount;
// 引用計數
t* _ptr;
// 指向管理資源的指標
mutex* _pmutex;
// 互斥鎖
};
關於這個智慧型指標的一些問題:
迴圈引用
執行緒安全
記憶體洩漏
C和指標 動態記憶體分配
void malloc size t size 分配所需的記憶體空間,並返回乙個指向它的指標。記憶體塊的大小,以位元組為單位。void calloc unsigned int num,unsigned int size 功能 在記憶體的動態儲存區中分配num個長度為size的連續空間,函式返回乙個指...
C 動態記憶體管理
我們都知道在c 中可以用new malloc動態分配記憶體空間,delete free釋放動態開闢的記憶體空間。1.那麼既然c 中有了可以動態開闢記憶體的函式為什麼又要有new delete呢?c 中的malloc free是繼承c語言中的malloc free,它的用法和在c語言中的用法一模一樣。...
C 動態記憶體管理
1 總結並剖析malloc free和new delete之間關係和差異。1 他們都是動態記憶體管理的入口 2 malloc要計算空間大小,返回值要強轉 new自動計算位元組大小,返回值是相應型別的指標 3 malloc只開闢空間 new開闢空間 呼叫建構函式初始化 delete呼叫析構函式清理 釋...