Re: [問題] 請問一下為何要使用new?

看板C_and_CPP作者 (藍影)時間14年前 (2011/11/23 17:35), 編輯推噓6(6017)
留言23則, 12人參與, 最新討論串2/2 (看更多)
我們把原本的 code 整理一下吧, int a = 10; int *pa; pa = new int; pa = &a; *pa = 20; 說明時主要以此例為架構, 接下來畫圖時間,下面述敘我比較少看到課本說明, 只考慮基本資料型態 POD 型態 (int, char, short, long long, double..etc) 不考慮 struct, class, 等自定義型態; 亦不考慮程式碼中有被 compiler 優化過。 ※ 引述《sd016808 ()》之銘言: 1. 直接給值 int a; 當作這動作時,程式會自己在憶體裡面找一個位址放 a 。 由於 int 這大小是 4 bytes, 所以會直接分配一個 4bytes 大小位址給 a Var. int a ┌──┬─────┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr │... │ 0x12~0x15│ │ │ │ │ │ │ │ │ ┌──┬─────┬──┬──┬──┬──┬──┬──┬──┬──┐ Value │... │ ??????? │ │ │ │ │ │ │ │ │ └──┴─────┴──┴──┴──┴──┴──┴──┴──┴──┴ 一樣的,今天做了「宣告同時給初值時」,動作類似,唯一開始就在 Addr 給初值。 int b=10; Var. int a int b ┌──┬─────┬──┬─────┬──┬──┬──┬──┬──┐ Addr │... │ 0x12~0x15│... │0x20~0x23 │ │ │ │ │ │ ┌──┬─────┬──┬─────┬──┬──┬──┬──┬──┐ Value │... │ ??????? │... │ 10 │ │ │ │ │ │ └──┴─────┴──┴─────┴──┴──┴──┴──┴──┴ a = b; 而這段敘述是,程式到 b 的位址撈值出來,丟給 a,所以最後 a 裡面的值就是 b Var. int a int b ┌──┬─────┬──┬─────┬──┬──┬──┬──┬──┐ Addr │... │ 0x12~0x15│... │0x20~0x23 │ │ │ │ │ │ ┌──┬─────┬──┬─────┬──┬──┬──┬──┬──┐ Value │... │ 10 │... │ 10 │ │ │ │ │ │ └──┴─────┴──┴─────┴──┴──┴──┴──┴──┴ 上面這些,變數對應到哪個位址,都是由程式掌控。 2. 間接給值 (pointer) 假設一開始只有 int a; Var. int a ┌──┬─────┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr │... │ 0x12~0x15│ │ │ │ │ │ │ │ │ ┌──┬─────┬──┬──┬──┬──┬──┬──┬──┬──┐ Value │... │ ??????? │ │ │ │ │ │ │ │ │ └──┴─────┴──┴──┴──┴──┴──┴──┴──┴──┴ 再來是先宣告一個指向整數的指標, 注意到,只要是指標,它存的 永遠都是記憶體的位置值 (開頭位置), 既然是存位置,所以記憶體給它的大小永遠都是固定的。故 int *pa; double *pa; char *pa; 不論是哪種,都是給它 4bytes (假給程式都是固定給指標 4bytes 存位置) 現在要藉由指標,讀寫 a ,而 a 的資料型態是 int,故宣告成指向int之指標 int *pa; 只有這樣宣告時,記憶體配了一個空間 (剛說了,假設是 4bytes) 給 pa Var. int a int *pa ┌──┬─────┬──┬──┬─────┬──┬──┬──┬──┐ Addr │... │ 0x12~0x15│... │ │0x20~0x23 │ │ │ │ │ ┌──┬─────┬──┬──┬─────┬──┬──┬──┬──┐ Value │... │ ??????? │... │ │ ??????? │ │ │ │ │ └──┴─────┴──┴──┴─────┴──┴──┴──┴──┴ 而第三步驟時, pa = new int; 這動作事實上是由二個動作合併成一個的。 一開始程式找一個新的空間配一個 int 大小記憶體 (4bytes) 出來, 而這個空間標示成 _address,假設這新的空間是 Var. int a int *pa _address ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Addr │... │ 0x12~0x15│... │ │0x20~0x23 │ │ 0x30~0x33│ │ ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Value │... │ ??????? │... │ │ ??????? │ │ ????? │ │ └──┴─────┴──┴──┴─────┴──┴─────┴──┴ 再來才把 _address 這個「位置」丟給 pa,所以 pa 現在存的就是那份新位置開頭, 也就是 0x30 Var. int a int *pa _address ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Addr │... │ 0x12~0x15│... │ │0x20~0x23 │ │ 0x30~0x33│ │ ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Value │... │ ??????? │... │ │ 0x30 │ │ ????? │ │ └──┴─────┴──┴──┴─────┴──┴─────┴──┴ pa = &a; 接下來這動作,又把 a 取位置 (&a),再丟到 pa 的內容去。 ( 因為 pa 是指標,所以一定是存「位置值」 ) Var. int a int *pa _address ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Addr │... │ 0x12~0x15│... │ │0x20~0x23 │ │ 0x30~0x33│ │ ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Value │... │ ??????? │... │ │ 0x12 │ │ ????? │ │ └──┴─────┴──┴──┴─────┴──┴─────┴──┴ *pa = 20; 這行動作,也同等拆也二部份,一開始 *pa , 根據 pa 裡面存的 0x12,去標記 0x12 為 _addr2 _addr2 Var. int a int *pa _address ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Addr │... │ 0x12~0x15│... │ │0x20~0x23 │ │ 0x30~0x33│ │ ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Value │... │ ??????? │... │ │ 0x12 │ │ ????? │ │ └──┴─────┴──┴──┴─────┴──┴─────┴──┴ 再來再整段看, *pa=20,去把剛剛標記的 _addr2 改成 20 _addr2 Var. int a int *pa _address ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Addr │... │ 0x12~0x15│... │ │0x20~0x23 │ │ 0x30~0x33│ │ ┌──┬─────┬──┬──┬─────┬──┬─────┬──┐ Value │... │ 20 │... │ │ 0x12 │ │ ????? │ │ └──┴─────┴──┴──┴─────┴──┴─────┴──┴ 檢視剛剛的成果出來 int a; int *pa; pa = &a; *pa = 20 所以最後用了 pa 去改 a 值, cout << a << endl;cout << *pa << endl; 答案都是 20,原理上面都已說明。 至於剛剛先用到的 pa = new int; ,那份 _address 到現在還卡在記憶體裡面, 以後就沒辦法再去控管它了,稱 memory leak。 至於 memory leak 現象這有很多說明了,本文不探討。 若是卡在 new 是什麼意思不知道 ---> 只能說該死了。 : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : BCB : 問題(Question): : 想請問一下new所代表的意思? : 例如 : int a=3,*ptr; : char buff[3]; : ptr=new int;// 這行代表說建立一個int大小的空間並讓ptr指定? : ptr=&a; : sprintf(buff,"%d",*ptr); : Edit1->Text=buff; : 想請問一下有打第3行跟沒有打 到底有什麼差別? -- No matter how gifted you are, alone, can not change the world. -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.78.41

11/23 17:45, , 1F
我想建議: 紙筆畫圖(or電繪)再傳圖檔到免費空間上,應該
11/23 17:45, 1F

11/23 17:45, , 2F
比BBS繪圖來的省時間.
11/23 17:45, 2F

11/23 17:47, , 3F
感謝 eric~ 建議 , 確實應該較省時 :)
11/23 17:47, 3F

11/23 17:53, , 4F
推這篇 辛苦了
11/23 17:53, 4F

11/23 18:32, , 5F
辛苦了
11/23 18:32, 5F

11/23 19:39, , 6F
ptt自己就有可以傳圖的http://ppt.cc/cut/
11/23 19:39, 6F

11/23 20:41, , 7F
ptt ppt
11/23 20:41, 7F

11/23 22:07, , 8F
*pa 是不是要寫成 pa 啊?
11/23 22:07, 8F

11/23 22:08, , 9F
抱歉,搞錯了,沒發現前面還有int 搞成dereference
11/23 22:08, 9F

11/23 23:16, , 10F
請問一下執行pa= new int這行時 新建的記憶體空間裡面的
11/23 23:16, 10F

11/23 23:16, , 11F
VALUE是?
11/23 23:16, 11F

11/23 23:20, , 12F
我若寫car *ptr; *ptr= new car; 這樣寫代表說新增的
11/23 23:20, 12F

11/23 23:22, , 13F
記憶體空間的VALUE值是?
11/23 23:22, 13F

11/23 23:23, , 14F
car 是我建的class結構名稱
11/23 23:23, 14F

11/23 23:27, , 15F
沒給初始值就是???
11/23 23:27, 15F

11/24 00:55, , 16F
@sd016808: 我認為你不該跳tone跳那麼快,POD都不熟就跳
11/24 00:55, 16F

11/24 00:56, , 17F
non-POD.只寫 new int 會配置空間,但不會給值.這個我圖
11/24 00:56, 17F

11/24 00:56, , 18F
裡面看得出來吧? 裡面是打問號.不是填零。
11/24 00:56, 18F

11/24 09:09, , 19F
其實我覺得版主應該把tropical72對於指標的圖都m起來
11/24 09:09, 19F

11/24 09:10, , 20F
這樣以後就不用再畫了.叫她們直接去看就好
11/24 09:10, 20F

11/24 18:42, , 21F
把大大的圖加到14誡XD
11/24 18:42, 21F

11/24 22:12, , 22F
讚 推推Y
11/24 22:12, 22F

02/01 21:55, , 23F
大推~~~!! 辛苦了~~~
02/01 21:55, 23F
文章代碼(AID): #1EpBv8oW (C_and_CPP)
文章代碼(AID): #1EpBv8oW (C_and_CPP)