推 LPH66:你弄錯 resize 要做什麼了: 他要你 resize 自己不是生個新的 04/13 14:28
我知道,不過我覺得直接弄一個新的丟回去比較簡單._.
→ MOONRAKER:你newVec看起來沒有在任何地方指定給別人啊。 04/13 16:26
推 LPH66:你要丟回哪裡去? 使用者期待的是物件自己有變動啊 04/13 16:57
不太懂......0.0
我還是解釋一下resize的作用好了
resize(unsigned place, Complex cpx)
這個函式會傳入一個整數place,還有一個Complex cpx。
如果傳入的整數比vector的資料個數還大,那就把vector擴張到適合的大小,並且從原本
的資料之後一直到place的位置都填入cpx,如果當初沒有傳入cpx則填0
如果傳入的整數比vector裡面資料個數還少,那vector大小不變,但原本的資料從尾開始
砍到剩下符合的數量
例如說原本VectorCpx v1是[1][2][3][4][5][ ][ ][ ],資料個數是5,容量是8
此時v1.resize(10,6),因為10比5大,因此v1必須擴張到能夠大以塞入至少10筆資料
而原本的容量8不夠大,因此要擴張為16,之後v1裡要放入10筆資料
前面都是舊資料,後面一直到第10筆則全部填入"6"
因此變成[1][2][3][4][5][6][6][6][6][6][ ][ ][ ][ ][ ][ ],資料個數是10,容量是16
如果是v1.resize(7,6),雖然7比5大,但還在容量8範圍內,因此不用擴張陣列
變成[1][2][3][4][5][6][6][ ],資料個數是7,容量是8
如果是v1.resize(3,6),3比5小,因此不會塞入新的資料,反而舊資料要從尾砍到剩下3筆
容量不變,變成[1][2][3][ ][ ][ ][ ][ ]
至於resize(unsigned place)則是一種overload而已
我的想法是這樣:
與其要大費周章的去改變原本的v1的大小,把資料搬來搬去最後再回傳回去
倒不如直接創一個新的VectorCpx來實作這個功能
如果v1需要擴張的話,就創一個VectorCpx newVecBig(place,cpx)
這個vector的容量是我要的,資料數也是我要的,不一樣的是這個vector裡沒有舊資料
因此再把舊的資料一筆筆覆蓋到newVecBig相對應的位置上
如果v1不需要擴張,則創一個與v1相同大小的空VectorCpx newVecSmall
這個vector裡面沒有存任何的資料,因此把舊的資料一筆筆貼到相對應的位置
貼到我當初要求的資料數(place值)為止
最後再把v1 delete掉,回傳newVecBig或newVecSmall,這就是我要的vector
不過現在問題就出在不知道為什麼印出來的值仍然是v1的值......
不知道我哪裡觀念錯誤0.0
→ diabloevagto:你回傳新東西是那招= = 04/13 17:20
→ diabloevagto:你傳回新的東西之後,你有把舊的記憶體釋放,然後 04/13 18:30
→ diabloevagto:回傳新的東西,但是你並沒有東西去接住 04/13 18:31
→ diabloevagto:原本的v1還是指向原本的v1,而不是你新回傳的 04/13 18:32
→ diabloevagto:你的解釋沒錯,但你複製之後應該要改掉原本的v1 04/13 18:32
喔喔大概開始有點概念了......
不過不太知道要怎麼改,請問是用像是 this -> newVec之類的方法嗎?
(不過編譯器不給我過就是,囧)
→ o07608:需要求救阿......OAQ 04/13 22:09
→ linotwo:就用你原本覺得大費周章的方式做一遍吧。 04/13 22:12
→ o07608:也不知道大費周章的方式怎麼做......只能想到這種方法 04/13 22:19
→ o07608:而且沒有搞清楚之前總是覺得不甘心._. 04/13 22:19
→ linotwo:配置一塊新空間 搬移 釋放舊空間 將 pCpx 指向新空間 04/13 22:22
→ linotwo:更新 mSize, mCapacity 04/13 22:22
喔......還有這種方法,之前居然都沒想到,囧
感謝你的提醒......
可是我還是好想知道我原來的想法觀念要怎麼實行阿 <囧>
→ linotwo:物件宣告完記憶體位址就是固定的。所以可以利用指標, 04/13 22:57
→ linotwo:隨時讓指標指向新的位址。如果有 N 個指標就要更新 N 次 04/13 22:58
→ linotwo:剛好你的物件裡有個 pCpx 可以讓你指,那顯然所有人都透過 04/13 22:59
→ linotwo:pCpx 是最方便的。 04/13 23:00
err......不好意思,我發現我不會指,囧
如果我沒理解錯你的意思的話,那應該是要把舊vector的每個空間的pCpx
指向新的vector的每個空間的pCpx指向的位址?
但是以我對這段話及對pointer觀念的理解,寫不出來囧......
for(unsigned int i = 0; i < mCapacity; i++)
*pCpx[i] = &newVec.pCpx[i];
這是我目前想出來的鬼東西......
→ diabloevagto:原po的想法不是本來就應該要用 linotwo 的方式實現嗎 04/13 23:16
→ o07608:因為我很固執,很想看到我原本的作法能成功...... 04/13 23:36
→ o07608:雖然知道linotwo的作法會更好...... 04/13 23:37
→ rephansu:resize回傳根本就沒意義啊...XD 04/13 23:47
→ o07608:0.0? 04/13 23:49
→ diabloevagto:你的程式不能跑 04/13 23:51
→ diabloevagto:抓那三個也一樣,說 DBL_MIN 沒定義 04/13 23:52
0.0?
如果不管我剛才加的那段程式碼的話(那段是錯的),應該是可以跑才對阿......
只是他cmd視窗不會有東西,會另外開一個.txt檔印出結果
→ diabloevagto:你印出的txt也沒東西= = 04/13 23:55
→ rephansu:DBL_MIN在float.h 04/13 23:55
我自己建專案跑的時候,至少確定可以印出A、B兩段阿0.0
而且也沒有跳警告說DBL_MIN找不到......奇怪
→ diabloevagto:反正你的問題就是你resize回傳的newVec沒有去用v1接 04/13 23:58
→ diabloevagto:你把main的v1.resize(10);改成v1=v1.resize(10); 04/13 23:58
結果程式當掉了......
→ rephansu:會當掉是因為resize時已經delete pCpx 04/14 00:04
→ diabloevagto:你resize回傳的時候,newVec就會被回收掉了吧 04/14 00:06
我還以為我delete的是原本v1的pCpx?!
→ diabloevagto:我跑程式不會當掉耶... 04/14 00:07
→ o07608:O囗Q 04/14 00:07
→ diabloevagto:你改成用指標傳就可以 04/14 00:21
→ diabloevagto:跟那個 delete[] pCpx; 無關 04/14 00:21
→ diabloevagto:後面加上 //<----this 04/14 00:24
error C2679: 二元運算子 '=' : 找不到使用右方運算元型別 'VectorCpx *' 的運算子
(或是沒有可接受的轉換)
所以說我連operator=的重載函式都寫錯了嗎......
→ diabloevagto:我是用你給的程式,改過四個地方而已 04/14 01:05
→ diabloevagto:還有把你 file << v1 << v2 << v3; 之後的都刪掉 04/14 01:06
→ o07608:怎麼會這樣...... 04/14 01:12
→ rephansu:總之觀念有錯... 04/14 01:19
→ rephansu:假設物件是房子, pCpx是屋內的家庭成員, resize時 04/14 01:21
→ rephansu:又蓋了一棟房子newVec,裡面的成員是複製原始v1的成員, 04/14 01:23
→ rephansu:最後又把v1房子內的成員清空, 因此v1不存在合法成員 04/14 01:25
→ rephansu:resize這個成員函式做的事情要很明確只有重新配置pCpx 04/14 01:28
→ rephansu:你必須要在這個function內完成這個工作, 04/14 01:29
→ rephansu:若要不修改原始code, 只需要在delete[] pCpx後加上 04/14 01:35
→ rephansu:memcpy(this, &newVec , sizeof(VectorCpx)); 04/14 01:36
→ rephansu:newVec.pCpx = NULL; 04/14 01:36
→ rephansu:這樣就可以達到你的目的... 04/14 01:41
→ rephansu:你一開始問到為何印出仍是舊的,答案是delete[] pCpx時, 04/14 01:43
→ rephansu:pCpx指向的記憶體位置資料尚未被改變, 04/14 01:43
→ diabloevagto:請問如果他這樣改了,但是回傳的是new的位址, 04/14 01:46
→ diabloevagto:但是他在離開resize的時候就會被回收掉了,這樣錯吧 04/14 01:47
→ rephansu:所以印出的結果會是一樣,但這卻是不合法的取值, 04/14 01:47
→ rephansu:一般會建議用SAFE_DELETE的方式刪除(google有詳細) 04/14 01:49
→ rephansu:newVec在return時的確會被delete,但我在return之前將 04/14 01:52
→ rephansu:newVec.pCpx指向非法位置 04/14 01:52
→ rephansu:這樣就可以將newVec.pCpx存留在v1.pCpx 04/14 01:53
→ diabloevagto:所以這也就是存取已經被刪除的變數,什麼時候會爆炸 04/14 01:56
→ diabloevagto:都有可能摟? 那如果照我上面那樣改成指標可以嗎? 04/14 01:56
→ diabloevagto:改成指標去回傳,並且存取 04/14 01:56
這裡我想搞清楚一下0.0
所以rep大修補我的程式的方法是:
因為原本我的程式碼在delete[] pCpx之後,pCpx指向的記憶體位置裡的資料仍然沒變
(Q1:那請問我delete掉的是什麼?)
因此利用這段程式碼
memcpy(this, &newVec , sizeof(VectorCpx));
newVec.pCpx = NULL;
(Q2-a:我有上網查過memcpy的用法和解釋,但還是不懂為什麼可以用在這邊......)
(Q2-b:為什麼要把newVec.pCpx指向NULL?)
來把newVec.pCpx指向非法位址
(Q3:為什麼指向NULL是非法位址?因為他照理來說會在return時被delete掉嗎?)
就可以把newVec.pCpx留在v1.pCpx,以避免return時newVec被delete掉
(Q4:為什麼newVec在return時會被delete掉?)
大概是以上幾個問題還沒搞懂......
推 LPH66:感覺有個觀念要再提一次 (雖然 rep 在上面某處提過了) 04/14 12:20
→ LPH66:resize 不需要回傳東西, 使用者期望的功能是物件自己有變動 04/14 12:21
→ LPH66:所以原 PO 你在 resize 裡寫 return 就是這個觀念錯了而已 04/14 12:21
→ LPH66:所以討論到底 newVec 要給誰接個人覺得有點怪怪的就是 04/14 12:23
→ LPH66:那後來 rep 在提的方法其實就只是 swap 的概念而已 04/14 12:24
→ LPH66:把自己跟 newVec 的內容物進行交換 之後 newVec 就能扔了 04/14 12:25
感謝各位不厭其煩一直替我解惑......m(_ _)m
目前程式還是先依照我原本的作法,在rep大提供了那兩行程式碼後已經完成了99.9%
剩下的0.1%是個main裡奇怪的小問題:
v3.push_back(Complex(0.5566, 0.9527)).push_back(Complex(0.2, 0.3));
這樣會出問題,似乎是讀不到後面的push_back
v3.push_back(Complex(0.5566, 0.9527));
v3.push_back(Complex(0.2, 0.3));
這樣就對了
而push_back的程式碼內容都沒變,不知道為什麼......
除此之外,這個程式基本上已經完成了
等段考完後,我會再用原本應該要用的正確觀念─使用者期望物件自己的變動
來把這個程式重寫一遍,不過這次也是學到了很多東西
現在希望先能把rep大講的那些東西好好搞懂......
(問題在上面0.0)
再次感謝大家的不辭勞苦 m(_ _)m
→ o07608:等那些問題搞懂,寫好註解之後,我再把目前最終版程式碼 04/14 15:02
→ o07608:貼上來0.0 04/14 15:02
→ o07608:請問有人能幫我解惑嗎......0.0? 04/14 22:54
→ zetab:delete只是告訴OS這個空間不再使用 並不會清掉空間裡的資料 04/15 00:18
→ zetab:memcpy幫你把newVec的資料複製到你目前的這個物件 04/15 00:37
→ zetab:把指標指向NULL只是讓你不小心存取到這個指標時看得出錯誤 04/15 00:39
→ zetab:提取NULL指標的內容會產生runtime error 讓你看得出錯誤 04/15 00:40
→ zetab:newVec是local variable所以離開function後就會消失 04/15 00:41
→ zetab:return一個local variable的reference不合法的 04/15 00:43
→ zetab:感覺你似乎不清楚變數的生命週期 先把這部分搞懂吧 04/15 00:44
總之我這次捅了個麻煩的大洞......0.0,等考完我再把這部份好好的磨助教磨到懂
以下是目前的最終版本
VectorCpx.h:http://ideone.com/qT1F8O
VectorCpx.cpp:http://ideone.com/J00SSs
main.cpp:http://ideone.com/awxpCS
有大家的幫忙,才能完成這份功課
最後希望我明後天的期中考能順利過關>"<
※ 編輯: o07608 來自: 220.133.35.4 (04/15 18:39)
→ o07608:話說codepad最近怎麼都連不上去...... 04/15 18:41