我以為我傳的是陣列,但居然傳的是指標?為什麼我無法回傳陣列?只能回傳指標?所以陣列和指標是什麼關係?指標運算怎麼算?釋放動態記憶體時,指標變數會不會也被釋放?
這是一篇中山資工所 江明朝老師 物件導向程式設計課程筆記,如內容有錯,歡迎留言交流~
還是很困惑嗎?文章裡有答案喔~😎
ㄧ、陣列 (Array)
原始碼是一個陣列,但編譯後就變成指標,所以陣列和指標到底有什麼關係?
a其實是一個指向第一元素的常數指標,i為index,N是 one past the end,最後一個元素後一個位置。
如果想要弄一個index為1開始的陣列,該如何實作?
int a[10]; int *p = a -1; // p[1] == a[0]
建議陣列的大小一開始先定義在一個常數變數上,未來要更動陣列大小時,就會比較方便!!
更多指標與陣列的關係例子,請參考期中考第2和5題。
雖然陣列名稱是一個指標變數,但還是有點不一樣:
例子(1)可以發現,傳陣列給func()中,但引數b的大小是sizeof(int)*1,所以傳陣列給函式時,我們傳的是指標。例子(2)可以發現,直接檢查陣列a的大小,會顯示sizeof(int)*10,因此如果再呼叫func(a);,會顯示sizeof(int)*1。
從例子(1)可知,傳陣列給函數,會以指標的方式傳給函數,因為這樣會比較有效率。在函數存取時,可以使用陣列的[]存取,也可以使用指標的*存取。
void function (int a[]); == void function (int *a); // int a[] == int *a for passing arguments
那如果要回傳陣列出來呢?此時就不能直接回傳陣列,而是要回傳指標,因為我們傳給函式的陣列,其實是一個指標,而非陣列,因此回傳時也要回傳指標出來。
另一種回傳陣列的方法是,將陣列包裹在struct / class中。
陣列的讀取有分by row或是by column,而為什麼C++函式參數列中,陣列的第一維可以不用給數字?
因為不需要第一維的數字,C++知道第二維長度就可以自動判斷出第一維長度。例如一個3x4的a陣列,傳陣列參數時,只要寫a[][4]即可。C++知道這是一個12大小,第二維為4的陣列,自然第一維就是3。
int a[2][5]; a[0][5] == a[1][0];?
complie error,不一定總是會成立,因為可能有些設計是by row或是by column
在陣列中,byte和element要有所區分,因為byte == sizeof(element),byte會隨著陣列裝的東西有關,但index不會。byte和element的區分,在指標運算中很重要。如果只是單一指標和常數的四則運算,這是記憶體位置的運算,因此和byte有關;而如果是指向同陣列的兩指標做加減,這是兩指標距離的運算,因此和element有關。
更多陣列的指標運算的例子,請參考期中考第3和4題
指標為存放記憶體位址的變數型態!指標是位址,位址是整數,但指標不是整數!
如果參數不必修改,建議多使用const。
__1__ int * __2__ ptr; // 在讀C++的型態時,由後往前讀!!
__1__ int __2__ * __3__ ptr; // __1__ == __2__:兩者位置皆相同
剛new出來的東西是沒有名字的,new出來的東西位址要存放在指標中,用這個指標去存取這個新東西。new除了可以配置動態記憶體外,也可以做初始化的動作。
如果new後沒有delete,可能會造成記憶題遺失,所以使用new,就一定要使用delete!然後delete是釋放指標所指向的物件,而非指標本身被釋放!因此被釋放的空指標仍可以重複再指向新的物件。建議釋放記憶體後,要給指標接上nullptr,避免重複釋放記憶體,重複釋放記憶體會造成錯誤。但如果多多使用STL,就不會造成記憶題遺失,因為它會自動幫你配置予釋放記憶體。如:C++ <vector>。
© blink.com.tw