最近為了面試K了很多C的知識,連帶的objective c有些東西也通惹!在這邊記錄一下!
先來看段C的link list code:
void insertNodeToList(linkNode *list, int data){ linkNode newNode = (linkNode)malloc(sizeof(Node)); newNode -> data = data; newNode -> next = NULL; linkNode current = *list; linkNode previous = NULL; if(*list==NULL){ *list = newNode; } else{ while(current != NULL){ previous = current; current = current -> next; } previous -> next = newNode; } }
上面這段code是小時候剛學資料結構的時候常常會寫到的東西,比較重要的幾個pointer:
//alloc一塊memory並讓newNode 這個pointer指著 linkNode newNode = (linkNode)malloc(sizeof(Node)); //指著link list 的開頭 linkNode current = *list; linkNode previous = NULL;
上面pointer一開始的狀態是先alloc一塊memory給newNode這個pointer指著(注意如果沒有pointer指著這塊記憶體的話,會發生memory leak的問題),然後current這個pointer指著*list這個pointer,previous只是在traversal的時候需要記住目前的pointer位置,如下圖:
此時如果把newNode插入到link list最尾端,如下圖
上面這段過程小時候應該超級熟悉的->link list插入,只是小時候常常只是照摳程式碼,然後可以動就可以惹,完全忽略為什麼link list用完要free啊之類的小細節,看著大家這樣寫就跟著這樣寫,考試考過就OK的想法,結果現在留了一對債要還QQ!回歸正題,再來看一段free的code
void freeList(linkNode *list){ linkNode current = *list; while(current != NULL){ linkNode tmp = current; current = current -> next; free(tmp); } *list = NULL; }
這段code說明把link list給全部free掉釋放記憶體,注意的是最後一行
*list = NULL;
如果沒有這行的話*list依舊指著該記憶體,只是不知道在指到的東西沒有意義(dangling)。看完這兩段小小的復習,大概可以知道pointer到底在做什麼,其實pointer的概念不難,難的是不知道用在哪裡,以及代表意義是什麼,其實總結一下pointer的功能:
用來指向某個已經分配記憶體的位址
復習完後整理一下大概會發生的bug scenario:
1. 如果alloc一塊memory給linkNode newNode,緊接這newNode = NULL,就會發生memory leak,導致這段記憶體區塊無法使用,如下圖
2. 如果同時有兩個pointer指著同一個memory記憶體位置,只要其中一個pointer free掉之後,另外一個pointer也不再擁有memory
接下來的部分是objectiv-c得記憶體管理,平常都用ARC的方式在寫code,ARC實在是很方便,只要我有一個strong的指標指著物件,該物間就不會被摧毀掉,直到該物間沒有任何的pointer指著他時,該物件才會被摧毀掉。但是如果是手動控管記憶體的話,可就沒有這麼方便惹,完完全全要回到以前寫c的時候,用人工去控制記憶體的分配,老實說實在是有夠麻煩,雖然現在大部分都用ARC,不過偶而還是會碰到iOS5以前的code,所以還是要瞭解一下,剛好最近投了一些APP的公司,東估一下西估一下,把理解的部分記下來。
先從retain和release說起:
NSString *str = [[NSString alloc]init]; NSString *str2 = str;
上面這段code代表str和str2同時指向同一塊記憶體(同一個物件),如果此時把str給摧毀掉,就會發生bug scenario2的情況,此時該怎麼辦呢?就要靠retain這個method惹,這個意思是我們需要對記憶體區塊做"保留"幾次,如果某個pointer被release掉了,而iOS說明如果該記憶體(物件)的retain count=0的時候,會自動摧毀該物件,導致str2所指的物件也跟著被摧毀,就可能會發生常常很討厭看到記憶體問題bug。
此時解決的辦法就是用
[str retain];
上面這一行code會修正bug scenario2,當str指到NULL或是其他物件時,str2所指向的物件依舊沒有被摧毀,效果如下圖:
知道retain和release之後,接下來就要來看常常會宣告的@property與@synthesis惹,估狗後得到的結論是如下:
- @property為宣告setter和getter
- 在MRC的scenario會用到的關鍵字:assign, retain, readwrite,readonly, copy, nonatomic
readwrite和readonly的概念很簡單,就是如果我宣告readonly的話,只會時作出getter,而readwrite的話會objective-c compiler會自動幫忙時作出getter和setter,在預設直上是設定readwrite。
assign只是單存的把指標指向該記憶體,就像上面link list插入時我們宣告的current一樣,如果把另外一個pointer給指到其他位址的話,一樣會造成scenario 2的問題,概念上就是沒有retain的意思,所以如果採用retain的話,就可以把scenario 2的bug給修正掉。
nonatomic,atomic是跟執行續有關的關鍵字,基本上盡量用nonatomic會比較好一點,也可以增加執行效率。以下就是常看到的:
@property(nonatomic,retain) UIWindow *window;
總結,在objective-c的記憶體管理上,概念幾乎都c相同,最近用功研讀了一下,發現不要把objective-c看成另外一種語言,其實概念幾乎都跟c相同,只是語法上比較奇怪一點,很多東西用c的想法幾乎都可以通,剩至可以用c來實做每一個method,只是很土炮,每個功能都要自己實作,好在有在公司接案寫App,讓我越來越理解objective-c的想法,個人認為objective-c基本上就是c語言+apple提供的framework+好用的物件概念吧!
參考資料:
沒有留言:
張貼留言