看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《xatier (xatier)》之銘言: : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : Ubuntu Linux / g++ 4.6 : 問題(Question): : http://ideone.com/f1Ctt : 我先用 operator new [] 要了一塊空間給 p 說好的 operator new[] 結果你用了 operator new .... : 之後想把 p 裏面每個元素都用 kerker 這個物件 initialize : 我的想法是透過 copy constructor 把 kerker 複製一份後塞給 p 裏面的空間 : 這樣似乎會造成 runtime error ? : 然後又做了實驗,把 : *p = T(kerker); 這個其實做了兩件事: 1. T temp(kerker); 呼叫 copy ctor 初始化一個暫時物件 2. *p = temp; 使用 copy assignment 把值複製進 *p 但事實上 temp 會被 optimize 掉,變成 kerker 直接 copy assigment 進 *p 所以執行時不會看到有關 temp 的東西 重點是,使用了 copy assigment 在這裡因為沒寫 operator= 所以使用預設 但 *p 根本還沒初始化過,string a 同樣也是沒初始化的狀態 呼叫 string::operator= 時死掉了 : 換成 : p = new T(kerker); : 這樣就能成功 這個也是做兩件事,但是不太一樣: 1. T temp(kerker); 呼叫 copy ctor 初始化一個暫時物件 2. p = &temp; 把 p 指向這個暫時物件 這並不會動到沒初始化的東西,所以 OK : 同樣都是去 call T 的 copy constructor : 兩者是差在那邊呢@@? 然後…最後要記得 for(int i=0; i<3; i++) p[i].~T(); operator delete[] (p);
QQ29:直接寫 T *p = new T[3]; 就可以啦05/31 23:34
在這個範例中確實可以 但如果今天 T 沒有 T() 可以用,這個方法就失敗了
xatier:根據網友 adxis 的水球,好像可以用 new (p+i) T(kerker);05/31 23:38
這是正解 不過不要忘記把 p++; 拿掉… 話說寫 p++; 的話之後不就不能用了嗎0.0 (除非再減回來)
xatier:研究中...05/31 23:38
QQ29:http://tinyurl.com/3yaaj4y 你那樣寫 就是他範例的case 305/31 23:39
QQ29:沒跑constructor 所以你的string a沒被建構 裡面出了啥差錯05/31 23:39
QQ29:不得而知05/31 23:40
QQ29:但是這樣就失去 placement new的意義了~05/31 23:41
xatier:Hmmm... 原來如此,我再試試看 >"<05/31 23:42
QQ29:啊我想錯了~用a大的方式就沒有錯 但是會發生exception原因05/31 23:44
QQ29:還是滿好奇的....05/31 23:44
我也不知道為什麼 placement new 還會發生 exception... orz
QQ29:你*p = 是呼叫T的operator = 但你沒寫這optr 所以她在做copy05/31 23:50
QQ29:的時候 string a = T(kerker).a 壞掉了05/31 23:51
-- 光明 的背後 是 黑暗 黑暗 的背後 還是 黑暗 由此可知 黑暗 > 光明 Q.E.D. -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.113.230.123 ※ 編輯: darkgerm 來自: 140.113.230.123 (06/01 02:17)
xatier:推薦這個萌神圳!清晰易懂! 06/01 02:15
※ 編輯: darkgerm 來自: 140.113.230.123 (06/01 02:19)
loveme00835:最後最好是那樣寫... 06/01 02:42
loveme00835:沒事看錯 06/01 02:43
不好意思,是我寫不清楚 如果這樣要到空間: T *p = (T *)operator new[] (sizeof(T) * 3); for(int i=0; i<3; i++) new (p+i) T(kerker); 那就要這樣 delete for(int i=0; i<3; i++) p[i].~T(); operator delete[] (p);
xatier:應該是直接 delete p[i] ? 06/01 02:43
loveme00835:p = new T(kerker); 不是暫時物件 06/01 02:45
恩…應該說是「配一個新的空間給 p」?
xatier:[問] 如果 delete p[i] 後再 operator delete [] (p) 會造 06/01 02:45
xatier:成 double free 的情況嗎@@ 不是說有 new 就要有對應的 06/01 02:46
xatier:delete,有 operator new [] 就要有 operator delete [] ? 06/01 02:46
xatier:darkgerm 學長直接呼叫 ~T() 是正確的作法嗎? 06/01 02:47
loveme00835:你的作法最好想成 malloc 一塊足以放置數個物件的記憶 06/01 02:49
loveme00835:體, 然後在每個適當位置建構起物件, 最後當然是要free 06/01 02:50
loveme00835:那一大塊記憶體, 但並不是在每個物件的所在各呼叫 06/01 02:51
loveme00835:delete 一次, 手動個別呼叫建構子也要手動解構物件, 06/01 02:52
loveme00835:所以這邊是正規的作法, 通常我就直接呼叫 C lib 函式 06/01 02:53
loveme00835:或是 std::allocator 來配記憶體了, 直接在語法上跟新 06/01 02:54
loveme00835:的 new operator 做區別 06/01 02:55
loveme00835:如果你真的作到把 operator new/delete 都 overload 06/01 02:57
loveme00835:或是類別只是簡單的 POD, 那解構子要不要呼叫就看各人 06/01 02:58
loveme00835:了 06/01 02:58
感謝版主的補充!
xatier:恩恩,我明白了,謝謝版主細心解釋!:D 06/01 02:59
loveme00835:我記得 Effective C++ 花蠻大篇幅講這個, 可以看看 06/01 03:03
xatier:我最近就在念這兩本XDDD 希望能把 C++ 學好 lol 06/01 03:24
linotwo:http://codepad.org/LxjasgEp 06/01 06:27
linotwo:可以直接用 new char[] 06/01 06:28
loveme00835:good job 06/01 11:38
透過 char* 跟系統要空間的方法真特別!! 不過要到的空間其實是用 char() 初始化過的 感覺和 uninitialized 不太一樣 ※ 編輯: darkgerm 來自: 140.113.230.123 (06/01 16:12)
linotwo:用 char 的原因是為了要能 delete 06/01 22:38
linotwo:如果不用 new / delete 的話直接用 malloc / free 就好 06/01 22:39