作者tropical72 (藍影)
看板C_and_CPP
標題Re: [問題] 請問一下為何要使用new?
時間Wed Nov 23 17:35:00 2011
我們把原本的 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
→ ericinttu:我想建議: 紙筆畫圖(or電繪)再傳圖檔到免費空間上,應該 11/23 17:45
→ ericinttu: 比BBS繪圖來的省時間. 11/23 17:45
→ tropical72:感謝 eric~ 建議 , 確實應該較省時 :) 11/23 17:47
推 Yshuan:推這篇 辛苦了 11/23 17:53
推 janice001:辛苦了 11/23 18:32
推 qpalwosk: ptt ppt 11/23 20:41
→ hakman:*pa 是不是要寫成 pa 啊? 11/23 22:07
→ hakman:抱歉,搞錯了,沒發現前面還有int 搞成dereference 11/23 22:08
推 sd016808:請問一下執行pa= new int這行時 新建的記憶體空間裡面的 11/23 23:16
→ sd016808:VALUE是? 11/23 23:16
→ sd016808:我若寫car *ptr; *ptr= new car; 這樣寫代表說新增的 11/23 23:20
→ sd016808:記憶體空間的VALUE值是? 11/23 23:22
→ sd016808:car 是我建的class結構名稱 11/23 23:23
→ diabloevagto:沒給初始值就是??? 11/23 23:27
→ tropical72:@sd016808: 我認為你不該跳tone跳那麼快,POD都不熟就跳 11/24 00:55
→ tropical72:non-POD.只寫 new int 會配置空間,但不會給值.這個我圖 11/24 00:56
→ tropical72:裡面看得出來吧? 裡面是打問號.不是填零。 11/24 00:56
→ angleevil:其實我覺得版主應該把tropical72對於指標的圖都m起來 11/24 09:09
→ angleevil:這樣以後就不用再畫了.叫她們直接去看就好 11/24 09:10
→ bernachom:把大大的圖加到14誡XD 11/24 18:42
推 Raymond0710:讚 推推Y 11/24 22:12
推 kimmyariel:大推~~~!! 辛苦了~~~ 02/01 21:55