對象創建限制在堆或棧
c++類對象的創建方式
- 對象創建限制在堆或棧
- C++ 中的類的對象的建立模式
- 如何將類限制在堆上呢?
C++ 中的類的對象的建立模式
C++ 中的類的對象的建立模式分為兩張:靜態建立,動態建立
- 靜態建立:由編譯器為對象在棧空間上分配內存,直接調用類的構造函數創建對象。例如:A a;
- 動態建立:使用 new 關鍵字在堆空間上創建對象,底層首先調用 operator new() 函數,在堆空間上尋找合適的內存并分配;然后,調用類的構造函數創建對象。例如:A *p = new A();
如何將類限制在堆上呢?
直觀的想法就是將構造函數設置為private這樣,靜態建立就無法創建對象,那么動態建立可以嗎?同樣不行,因為動態創建饒了半天,也需要調用構造函數
方法一:
將析構函數設置為私有,原因:靜態對象建立在棧上,是由編譯器分配和釋放內存空間,編譯器為對象分配內存空間時,會對類的非靜態函數進行檢查,即編譯器會檢查析構函數的訪問性。當析構函數設為私有時,編譯器創建的對象就無法通過訪問析構函數來釋放對象的內存空間,因此,編譯器不會在棧上為對象分配內存。
class A
{
public:A() {}void destory(){delete this;}private:~A(){}
};
- 但是這個方法有個問題,就是外部用delete的時候,析構函數由于是私有的,就無法釋放空間。那么就需要在內部實現delete釋放空間。
- 繼承的時候,如果基類將析構函數設置為虛函數,派生類重寫該虛函數來實現多態,由于基類析構函數是私有的,派生類就無法訪問。
方法二:
構造函數設置為 protected,并提供一個 public 的靜態函數來完成構造,而不是在類的外部使用 new 構造;將析構函數設置為 protected。原因:類似于單例模式,也保證了在派生類中能夠訪問析構函數。通過調用 create() 函數在堆上創建對象。
class A
{
protected:A() {}~A() {}public:static A *create(){return new A();}void destory(){delete this;}
};
限制對象只能建立在棧上:
解決方法:將 operator new() 設置為私有。原因:當對象建立在堆上時,是采用 new 的方式進行建立,其底層會調用 operator new() 函數,因此只要對該函數加以限制,就能夠防止對象建立在堆上。
class A
{
private:void *operator new(size_t t) {} // 注意函數的第一個參數和返回值都是固定的void operator delete(void *ptr) {} // 重載了 new 就需要重載 delete
public:A() {}~A() {}
};