只能在堆或棧上建立物件?

2021-06-08 21:51:18 字數 3001 閱讀 3594

1. 只能在堆(heap)上建立物件/禁止產生棧(stack)物件

建立棧物件時會移動棧頂指標以「挪出」適當大小的空間, 再在這個空間上直接呼叫對應的建構函式以形成乙個棧物件, 而當函式返回時會呼叫其析構函式釋放這個物件, 再調整棧頂指標收回那塊棧記憶體

, 在這個過程中是不需要operator new/delete操作的, 所以將operator new/delete設定為private不能達到禁止產生棧(stack)物件的目的.

把析構函式定義為private訪問許可權, 就可以保證只能在堆(heap)上建立(new)乙個新的類物件.析構函式私有化的類的設計可以保證只能用new命令在堆(heap)中建立物件, 只能動態的去建立物件, 這樣可以自由的控制物件的生命週期, 但這樣的類需要提供建立和撤銷的公共介面. 

class onlyheapclass  

void destroy()

private:

~onlyheapclass()

};

int main()

解析:c++是乙個靜態繫結的語言. 在編譯過程中, 所有的非虛函式呼叫都必須分析完成. 即使是虛函式, 也需檢查可訪問性. 在棧(stack)上生成物件時, 物件會自動析構, 即析構函式必須可以訪問. 而在堆(heap)上生成物件, 由於析構時機由程式設計師控制,所以不一定需要析構函式.

將析構函式設為private除了會限制棧物件生成外, 還會限制繼承. 如果乙個類不打算作為基類,通常採用的方案就是將其析構函式宣告為private. 為了限制棧物件,卻不限制繼承, 可將析構函式宣告為protected, 這樣就兩全其美了.如下**所示:

class   nostackobject   

public:

void destroy()

};

接著,可以像這樣使用nostackobject類:

nostackobject*   hash_ptr   =   new   nostackobject();   

... ... //

對hash_ptr指向的物件進行操作

hash_ptr->destroy();

是不是覺得有點怪怪的: 用new建立乙個物件, 卻不是用delete去刪除它, 而是要用destroy方法,使用者是不習慣這種怪異的使用方式的, 所以將建構函式也設為private或protected, 但需要讓該類提供乙個static成員函式專門用於產生該型別的堆物件. (設計模式中的singleton模式就可以用這種方式實現.)讓我們來看看:

class   nostackobject   

~nostackobject()

public:

static nostackobject* creatinstance()

void destroy()

};nostackobject* hash_ptr = nostackobject::creatinstance();

... ... //

對hash_ptr指向的物件進行操作

hash_ptr->destroy();

hash_ptr = null; //

防止使用懸掛指標

2. 只能在棧(stack)上生成物件

為禁止產生某種型別的堆物件, 可以自己建立乙個資源封裝類, 該類物件只能在棧中產生,這樣就能在異常的情況下自動釋放封裝的資源.

產生堆物件的唯一方法是使用new, 禁止使用new就可禁止產生堆物件

. 由於new執行時會呼叫operator new, 而operator new是可過載的, 所以將operator new和operator delete過載為private即可. 建立棧物件不需要呼叫new, 因為建立棧物件不需要搜尋記憶體, 而是直接調整堆疊指標將物件壓棧, 而operator new的主要任務是搜尋合適的堆記憶體, 為堆物件分配空間. 

#include //

需要用到c式記憶體分配函式

class resource ; //

代表需要被封裝的資源類

class nohashobject

void

operator delete(void* pp) //

非嚴格實現, 僅作示意之用

public:

nohashobject()

~nohashobject()

};

nohashobject現在就是乙個禁止堆物件的類了,如果你寫下如下**:

nohashobject* fp = new nohashobject(); //

編譯期錯誤!

delete fp;

上面**會產生編譯期錯誤. 好了, 現在你已經知道了如何設計乙個禁止堆物件的類了, 你也許和我一樣有這樣的疑問,難道在類nohashobject的定義不能改變的情況下, 就一定不能產生該型別的堆物件了嗎? 不, 還是有辦法的,我稱之為「暴力破解法」. c++是如此地強大, 強大到你可以用它做你想做的任何事情.這裡主要用到的是技巧是指標型別的強制轉換. 

int main()   

對於上面的這麼多強制型別轉換, 其最根本的是什麼了? 可以這樣理解:

某塊記憶體中的資料是不變的, 而型別就是我們戴上的眼鏡, 當我們戴上一種眼鏡後, 我們就會用對應的型別來解釋記憶體中的資料,這樣不同的解釋就得到了不同的資訊.

所謂強制型別轉換實際上就是換上另一副眼鏡後再來看同樣的那塊記憶體資料.

另外要提醒的是,不同的編譯器對物件的成員資料的布局安排可能是不一樣的, 比如大多數編譯器將nohashobject的ptr指標成員安排在物件空間的頭4個位元組,這樣才會保證下面這條語句的轉換動作像我們預期的那樣執行:

resource* rp = (resource*)obj_ptr;

但並不一定所有的編譯器都是如此.

整理 只能在堆或棧上建立物件?

1.只能在堆 heap 上建立物件 禁止產生棧 stack 物件 建立棧物件時會移動棧頂指標以 挪出 適當大小的空間,再在這個空間上直接呼叫對應的建構函式以形成乙個棧物件,而當函式返回時會呼叫其析構函式釋放這個物件,再調整棧頂指標收回那塊棧記憶體 在這個過程中是不需要operator new del...

只能在棧上或者堆上建立的物件

今天在這裡面看到了這個題目,據說還是google面試題。總的思想,是把一些在棧上或者堆上面建立物件,所必須的函式設為private使得編譯報錯。比如 只能在堆上建立,不能在棧上建立。因為棧上的物件,總是要呼叫析構函式。所以把析構函式設為private,然後new出來的物件,顯式的呼叫delete就可...

設計只能在堆或者棧上建立的類

看到了csdn一篇帖子在討論這個問題,某牛給出了回答,於是加以整理了一下 設計只能在堆上分配的類 方法 將類的建構函式或者析構函式設定為私有,迫使類物件在棧的構造時編譯出錯 include using namespace std class onlyheap 設計只能在棧上分配的類 過載new和de...