網頁

2013年10月20日 星期日

C++ memory & stack-allocated for local variable

Last Update: 2013/10/20 12:22+08
Type: note


Intro

Local Variable 的 memory 位置 和 return value
主要是要測試 class 在 function return 時 的問題
但用 int 比較方便解釋, 所以這邊用 int 作測 試
int get1(){ int rs = 1; printf("%d : %d\n", &rs, rs); return rs;}
int* get2(){ int rs = 2; printf("%d : %d\n", &rs, rs); return &rs;}
int& get3(){ int rs = 3; printf("%d : %d\n", &rs, rs); return rs;}
int& get4(){ int *rs = new int(4); printf("%d : %d\n", rs, *rs); return *rs;}



Content


case 1
int _tmain()
{
 printf("---case 1---\n");

 int idx1 = get1(); // 1899836 : 1
 printf("%d : %d\n\n", &idx1, idx1); // 1900144 : 1
 //位置不一樣, 沒問題






case 2
 printf("---case 2---\n");

 int *idx2 = get2(); // 1899836 : 2
 printf("%d : %d\n\n", idx2, *idx2); // 1899836 : 2
 //傳pointer, 位置一樣, 沒問題?


 *idx2 = 22;
 printf("%d : %d\n\n", idx2, *idx2); // 1899836 : 22
 // 指定該位置 為 22, 沒問題?


 int *idx2_2 = get2(); // 1899836 : 2
 printf("%d : %d\n\n", idx2, *idx2); // 1899836 : 2
 printf("%d : %d\n\n", idx2_2, *idx2_2); // 1899836 : 20518839
這邊再 get 另一個 int *idx2_2
你的 compiler 很可能跟我一樣
在執行 get2() 時, 被分配的記憶體, 跟上次一樣
這時問題就出現了
   1. 跟上次取得的idx2有衝突
   2. Why?

關於(1.): 沒錯 起衝突了, 所以我們列印 idx2 卻發現原本修改成 22 的數值 變成 2 了
關於(2.): 之所以會有這狀況是因為 stack-allocated. 我們在呼叫 function 時, local variable 會被暫存到其它地方, 直到 該function執行結束, 準備返回到原本的function時, 才會被寫回來.

所以 在 get2() 裡, 被配置的位置, 即使被傳回來 也應該是不能用的
像是line3. 僅只是經過了一個 printf, 同一個位置的值卻被改掉了. 主要是因為, 那個位置 在離開 get2() 後 就不屬於你的了, 也就是本來就沒有配置給你


 *idx2 = 23;
 printf("%d : %d\n\n", idx2_2, *idx2_2); // 1899836 : 23
想當然爾~ 如果改了 idx2, 會連同 idx2_2 一起改掉(同一個位置)
P.S. 即使2次分配的記憶體不同, 那個位置也不是能傳回來用的






case 3
咱們換成 & 來試試
 printf("---case 3---\n");
 int idx3 = get3(); // 1899836 : 3
 printf("%d : %d\n\n", &idx3, idx3); // 1899836 : 3

 int& idx3_3 = get3(); // 1899836 : 3
 printf("%d : %d\n\n", &idx3_3, idx3_3); // 1899836 : 3
 printf("%d : %d\n\n", &idx3_3, idx3_3); // 1899836 : 20331817
結果一樣, 在第二次 print idx3_3 時, 數值被改變了





case 4
使用 new 的方式, 是可以在離開 function (scope) 時, 保留該配置 (參閱 C++ new class or not
接著測試此方式
 printf("---case 4---\n");
 int idx4_bad = get4(); // 597336 : 4
 printf("%d : %d\n\n", &idx4_bad, idx4_bad); //1900084 : 4
 //delete &idx4_bad;//failed
如果咱們 單純的宣告一個 int 去接收它, 那只是接收了它的值
沒辦法刪除它(原本new出來的


 int& idx4 = get4(); // 618240 : 4
 printf("%d : %d\n\n", &idx4, idx4); // 618240 : 4
 delete &idx4;
咱們要宣告 int& 去接收它, 這樣他們才會指向同一個物件, 也才可以刪除它
P.S. new 出來的記憶位址跟其它的不太一樣


Conclusion
local variable 的配置 只在該 scope 有效
注意 傳入 及 傳回 的類型



沒有留言:

張貼留言