大雄
Lv 4
大雄 發問時間: 電腦與網際網路程式設計 · 1 0 年前

operator delete問題

請問各位大大下面的兩行

void operator delete (void* ptr, const std::nothrow_t& nothrow_constant)

void operator delete (void* ptr, void* voidptr2)

的意義是什麼呢,何時會用到呢?

謝謝!

已更新項目:

placement delete是自己必須去實做嗎?

因為網路上資料是說要自己去實做placement delete!

請問是不是呢?

謝謝!!

2 個已更新項目:

那void operator delete (void* ptr, const std::nothrow_t& nothrow_constant)意義是什麼呢?

3 個已更新項目:

想問"new (size_t, const char*, int)"中的"int"所輸入的參數有什麼意義呢?

有什麼書是建議看的呢?

謝謝!

4 個已更新項目:

原來如此!

但是"《Effective C++》(3版) "這一本書絕版了!不知道還有什麼好書能推薦呢?

謝謝!

5 個已更新項目:

T* place =new (nothrow) T;

T* pt = new (place) T;

operator delete (pt,place);

//operator delete (pt);這樣寫也能釋放記憶體

為什麼還要有operator delete (void* , void*);呢?

operator delete (pt,place);參數順序正確嗎?

謝謝!

6 個已更新項目:

發現錯誤了

char* place =new (nothrow) char[sizeof(T)];

T* pt = new (place) T;

delete pt;

7 個已更新項目:

>>delete (void* , void* ) 純粹只是為了和 new 作 signature 匹配,參數完全沒意義

剛剛有查了一下只要用delete pt;當T* pt = new (place) T出現錯誤的時候會自動調用operator new 匹配operator delete(void* operator new(size_t, void*)和void operator delete(void*, void*)) signature !

感謝!

8 個已更新項目:

為什麼void operator delete(void*, void*)裡面會空白這樣有意義嗎?

void operator delete(void*, void*)

{}

感謝!

9 個已更新項目:

我本來以為應該要

void operator delete(void* ptr1, void* ptr2)

{

delete ptr1;

}

感謝!

10 個已更新項目:

為什麼不是

void operator delete(void* ptr1, void* ptr2)

{delete ptr1;}

void operator delete(void*, void*)

{}

這樣能是放空間嗎?(我知道預設是這個)

這會不會是要自己實做這個才有意義呢?

謝謝!!

11 個已更新項目:

"是放"=>釋放

12 個已更新項目:

>>記憶體的來源,他可能來自

>>- operator new

>>- malloc

>>- stack

>>- global、static

>>- 自己或別人寫的 pool

>>- 由另一個 process 或 dll 所提供的共用記憶體

原來如此!也是

>>operator new/delete 和

>>new/delete expression

>>之間的差別

operator new/delete可以重載

new/delete expression無法重載=配置空間+初始化

13 個已更新項目:

確實要用 operator delete(ptr1);

感謝!

1 個解答

評分
  • novus
    Lv 6
    1 0 年前
    最佳解答

    >> 意義是什麼

    placement delete

    >> 何時會用到

    當你用到 placement new 的時候

    好,我知道你一定會問甚麼時候要用到 placement new

    正常的 new 把「配置記憶體」和「呼叫constructor」併在一起

    當你想兩件事情分開做的時候就需要 placement new

    2010-04-10 12:24:21 補充:

    1. 先來講 new expression,一般我們用的 new expression 型如等號右式

    T* pt = new T;

    new expression 會做兩件事:(1)是呼叫 operator new 配置記憶體,(2)呼叫 T 的constructor

    預設的 operator new 長這個樣子

    void * operator new (size_t) throw(std::bad_alloc);

    行為基本上和 malloc 一樣,輸入 size_t 然後輸出 void 指標,記住他只負責分配記憶體,對物件一無所知。

    一般人比較不了解的是,new expression 也可以加額外參數,像這樣

    T* pt = new("hellow world", 123456) T;

    這些參數會用來轉呼叫 operator new,像上面這例就必須提供對應 signature 的 operator new,否則會發生錯誤:

    void * operator new (size_t, const char*, int) throw(std::bad_alloc);

    這裡的 size_t會由 new expression 計算

    2. 有一種情況是記憶體配置完成,但是 constructor 丟出 exception,那麼必須要有一個釋放記憶體機制。由於不同的 operator new 有不同的記憶體配置方式,例如有的從 heap、有的從自製的 pool、有的則直接傳回現有的位址,因此沒有一體適用的釋放方式。

    new expression的解決方案就是尋找「和operator new匹配的那個operator delete」來做釋放工作。如果你提供了自定的operator new就一定要提供匹配的operator delete

    配對的方式如下

    void* operator new(size_t, 參數...)

    void* operator delete(void*, 參數...)

    這裡要特別強調一件事,delete expression本身不能帶參數,所以不可能透過delete expression來呼叫特定的 operator delete。

    3. 就你在這裡提到的兩個 placement delete 都是隨餐附贈,不用自己生,只要 #include 即可,很多時候你引用 STL 也會無意間引入

    型式1用法

    char buf[100];

    void* place = buf;

    T* pt = new(place) T; //不會配置新記憶體,直接將物件建立在place所指的位址上

    pt->~T(); // 不可用delete expression,因為記憶體來自stack,無法歸還。

    // 但可以直接使用 operator delete(void *, void *)

    型式2用法

    T* pt = new(std::nothrow) T;

    沒甚麼特別的功能,只不過是配置失敗的時候不會丟exception,而是傳回空指標。nothrow_t其實沒有任何意義,只不過是用來製造獨特的 signature 罷了

    如果你去看header,nothrow_t 九成是空的:struct nothrow_t {};

    說來故事非常長,本來想幾句話結束,結果不小心就打這麼多了.....我還沒說的大概是這裡的五倍,而且事實上我對這個主題還不算熟.....建議你在真的想做些甚麼之前先多看看書

    2010-04-10 12:26:30 補充:

    被吃字

    #include <new>

    2010-04-10 16:08:28 補充:

    基本知識可讀 《C++ primer》

    我建議你可以看看《Effective C++》(3版) 花了多少篇幅介紹這個議題

    那個 operator new 是我亂編的,參數的意義當然隨我高興

    2010-04-10 22:07:35 補充:

    我舉個例子

    你可以在程式碼加入下面的片段

    (這是錯誤示範,正確的實作要複雜得多)

    void* operator new(size_t size, int n) {

    cout << n << endl;

    return malloc(size);

    }

    接著就可以這樣用

    T* pt = new(123) T;

    free(pt);

    new expression會嘗試去搜尋是否有吃 (size_t size, int n) 的operator new

    然後就會找到上面提供的版本

    2010-04-12 00:45:23 補充:

    震驚 竟然絕版了...

    如果英文好的話

    上網查查資料吧

    這裡有提到一些實際的應用和觀念

    http://en.wikipedia.org/wiki/Placement_syntax

    但沒有提到自行實作的重要關鍵,很多瑣碎的東西真的是沒講你不知

    我建議是沒事不要自找麻煩

    2010-04-12 00:47:01 補充:

    剛發現一個小錯

    free(pt);上面要加一行

    pt->~T(); //如果有需要的話

    2010-04-14 01:43:20 補充:

    你的寫法有誤

    相當於在同一塊記憶體上建構了兩個物件,如果 T 的 ctor有作用的話會是災難一場。

    delete (void* , void* ) 純粹只是為了和 new 作 signature 匹配,參數完全沒意義

    時間晚了,容我賣個關子

    想想看不看header你有沒有辦法自己實作

    void* operator new(size_t, void*)和

    void operator delete(void*, void*)

    如果你想得出來的話,差不多就搞懂最基本的東西了

    2010-04-14 19:00:40 補充:

    >> delete pt;

    這樣的寫法不好,不小心就會歸還到不該歸還的記憶體。

    應該先

    pt->~T();

    然後手工呼叫適當的 operator delete 或功能相等的函數

    看看和你想得一不一樣

    預設的placement new、delete 實作類似這樣

    void* operator new(std::size_t, void* p)

    {

    return p;

    }

    void operator delete(void*, void*)

    {

    }

    2010-04-15 13:31:39 補充:

    不然你認為void operator delete(void*, void*) 應該要放哪些內容呢

    2010-04-15 18:12:30 補充:

    這樣說好了

    placement delete存在的目的在於,復原任何 placement new 所做的改變。

    因為這個 placement new 也沒做甚麼事,所以 placement delete 也樂得輕鬆

    2010-04-16 18:31:43 補充:

    不需要、也不應該釋放空間。因為 placement new 根本就沒有配置任何記憶體,他只是直接拿現有的記憶體來用。

    事實上你想自己寫 placement delete 也不知如何釋放起,因為你根本不曉得記憶體的來源,他可能來自

    - operator new

    - malloc

    - stack

    - global、static

    - 自己或別人寫的 pool

    - 由另一個 process 或 dll 所提供的共用記憶體

    直接 delete 會導致錯誤,嚴重的話會crash

    2010-04-16 18:37:24 補充:

    還有這樣寫也是錯的

    void operator delete(void* ptr1, void* ptr2)

    {delete ptr1;}

    你不應該用 delete expression

    因為 delete expression 不只會釋放記憶體,還會呼叫destructor

    應該用

    operator delete(ptr1);

    我覺得你可能從頭到尾都沒搞懂,我想確定一下你知不知道

    operator new/delete 和

    new/delete expression

    之間的差別

還有問題?馬上發問,尋求解答。