如果需要在堆上建立物件,要麼使用new
運算子,要麼使用malloc
系列函式。這點沒有異議。
真正有異議的是下面的**:
c++ 1
object
obj;
此時,obj
是在棧上分配的嗎?
要回答這個問題,我們首先要理解這個語句是什麼意思。這個語句就是代表著,在棧上建立物件嗎?
其實,這行語句的含義是,使物件obj
具有「自動儲存(automatic storage)」的性質。所謂「自動儲存」,意思是這個物件的儲存位置取決於其宣告所在的上下文。
如果這個語句出現在函式內部,那麼它就在棧上建立物件。
如果這個語句不是在函式內部,而是作為乙個類的成員變數,則取決於這個類的物件是如何分配的。考慮下面的**:
c++ 1
2
3
4
5
6
class
class
;
class
*pclass
=new
class
;
指標pclass
所指向的物件在堆上分配空間。因為object obj;
語句的含義是「自動儲存」,所以,pclass->obj
也是在堆上建立的。
理解了這一點,再來看下面的語句:
c++ 1
2
object
*pobj
; pobj
=new
object
;
object *pobj;
代表,指標pobj
是自動儲存的,僅此而已,沒有任何其它含義。而下面一行語句則指出,這個指標所指向的物件是在堆上面分配的。如果這兩行語句出現在乙個函式內部,意味著當函式結束時,pobj
會被銷毀,但是它指向的物件不會。因此,為了繼續使用這個物件,通常我們會在函式最後新增乙個return
語句,或者使用乙個傳出引數。否則的話,這個在堆上建立的物件就沒有指標指向它,也就是說,這個物件造成了記憶體洩露。
並不是說指標指向的物件都是在堆上建立的。下面的**則使用指標指向乙個在棧上建立的物件:
c++ 1
2
object
obj;
object
*pobj
=&obj
;
至此,我們解釋了函式內部的變數和成員變數。還有兩類變數:全域性變數和static
變數。它們即不在堆上建立,也不在棧上建立。它們有自己的記憶體空間,是除堆和棧以外的資料區。也就是說,當object obj
即不在函式內部,又不是類的成員變數時,這個物件會在全域性資料段建立,同理適用於static
變數。對於指標object *pobj;
,如果這個語句出現在函式內部或類的成員變數,正如我們前面所說的,這個指標是自動儲存的。但是,如果這個語句是在類的外部,它就是在全域性資料段建立的。雖然它指向的物件可能在堆上建立,也可能在棧上建立。
堆和棧的區別在於兩點:
生命週期
效能但是,有些情況,即便你在棧上建立了物件,它還是會占用堆的空間。考慮如下**:
c++ 1
2
3
4
void
func
物件v
是在棧上建立的。但是,stl 的vector
類其實是在堆上面儲存資料的(這點可以檢視源**)。因此,只有物件v
本身是在棧上的,它所管理的資料(這些資料大多數時候都會遠大於其本身的大小)還是儲存在堆上。
關於第二點效能,有影響,不過一般可以忽略不計。確切的說,一般情況下你不需要考慮效能問題,除非它真的是乙個問題。
首先,在堆上建立物件需要追蹤記憶體的可用區域。這個演算法是由作業系統提供,通常不會是常量時間的。當記憶體出現大量碎片,或者幾乎用到 100% 記憶體時,這個過程會變得更久。與此相比,棧分配是常量時間的。其次,棧的大小是固定的,並且遠小於堆的大小。所以,如果你需要分配很大的物件,或者很多很多小物件,一般而言,堆是更好的選擇。如果你分配的物件大小超出棧的大小,通常會丟擲乙個異常。儘管很罕見,但是有時候也的確會發生。有關效能方面的問題,更多出現在嵌入式開發中:頻繁地分配、釋放記憶體可能造成碎片問題。
現代作業系統中,堆和棧都可以對映到虛擬記憶體中。在 32 位 linux,我們可以把乙個 2g 的資料放入堆中,而在 mac os 中,棧可能會限制為 65m。
總的來說,關於究竟在堆上,還是在棧上建立物件,首要考慮你所需要的生命週期。當效能真正成為瓶頸的時候,才去考慮效能的問題。堆和棧是提供給開發者的兩個不同的工具,不存在乙個放之四海而皆準的規則告訴你,乙個物件必須放在堆中還是在棧中。選擇權在開發者手中,決定權在開發者的經驗中。
C 在堆上建立物件還是在棧上建立物件
對於 object obj obj是在棧上分配的嘛?其實,這個語句的含義是,使物件obj具有 自動儲存的性質 意思就是這個物件的儲存位置取決於其宣告所在的上下文。如果這個語句出現在函式內部,那麼它就在棧上建立物件。如果這個語句不是在函式內部,而是作為乙個類的成員變數,則取決於這個類的物件是如何分配的...
C 如何限制物件在堆上或棧上生成
1,限制類的物件只能生成在棧上 將 operator new 各種原型設為私有 include class onlyonstack onlyonstack private void operator new std size t size void operator new std size t s...
C 如何限制物件在堆上或棧上生成
1,限制類的物件只能生成在棧上 將 operator new 各種原型設為私有 include class onlyonstack onlyonstack private void operator new std size t size void operator new std size t s...