因為女兒就快要出生,所以最近都在找適合的彌月蛋糕,去了家附近的幾家蛋糕店,每家店給我的印象都不太一樣。
第一家,xx鄉,以蜂蜜蛋糕出名,彌月禮盒很可愛,是我喜歡的包裝,不過跟店員說我們想試吃時,她隨手拿了個塑膠袋,裝了兩三塊餅乾就遞給我們,讓我們感覺很差,很像我們是來騙東西吃得。
第二家,xx屋,有專門設計的小禮盒裝試吃的小蛋糕,和幾塊餅乾,比前一家有進步,蛋糕不錯,列為考慮之一。
第三家,喜憨兒烘焙屋,店員非常的客氣,留下了我的聯絡方式,說會幫我預定試吃禮盒,幾天後可以過來拿,我心想不就現場給我就好了嘛,幹麼這麼麻煩,回家後我馬上收到她們的來信,提醒我哪一天去拿試吃禮盒。幾天過後,因為太忙的緣故,我比原訂日期晚了兩天才去,本以為應該沒有了,不過她們說還保留著,但不能給我,是要懲罰我忘了這件事情嗎??不是,是因為過了最佳品嚐時間,怕口感變了,影響我的感覺。昨天晚上,我終於拿到了喜憨兒烘焙屋的彌月試吃禮盒,一塊小蛋糕,三塊餅乾,這雖然不是我吃過最好吃的蛋糕,但我真的非常非常的喜歡,因為充滿了濃濃的尊重與祝福。
2013年6月4日 星期二
Objective-C Pointer
Objective-C中,呼叫方法時,參數的傳遞是 call by value,也就是複製一份值傳遞進去,網路上的有些資料提到類似 call by reference,其實骨子裡還是 call by value。而要解釋這個概念前不得不先解釋指標(Pointer)。
指標 Pointer
我們先來看這一行,NSString * ptr = @"Content"; ,這裡宣告了一個指標ptr,指向一個NSString的物件,而這個物件的值是@"Content",數值於電腦運算時,都存儲於記憶體中,可以想成一條馬路上有許多房子,大小固定,都有門牌,而物件有大有小,有些可能需要好幾間房子打通才放得下。示意圖如下,Ptr所存的值( 0x100001040 )剛好是這個字串的記憶體位置,ptr本身也有個Address是 0x7fff5fbff898。由這個例子可以知道要知道門牌位置必須使用 & 取址運算子,在NSLog中用%p列印出來。
用一張圖來解釋發生什麼事情
當我們把o指標傳進方法後,複製了它的值給了m,而在方法中 m = @"Modify",又產生了一個物件NSString,m的值變成了@"Modify"的記憶體位置,所以不管我們在方法中怎麼改,原本的值不會有任何變化。
那如果我們想要的是直接更改原本的值,該怎麼做呢。有幾種方法,先講最容易的,把NSString改為NSMutableString,這樣在改值時,就會把原先的值,在原位置直接改變,而不是新產生一個新的物件。
這邊宣告一個變數o指向@"Origin",o的記憶體位置是f898,o的值是1048,也就是@"Origin"的記憶體位置,someOperate方法接受的參數為指標的指標,而也就是o指標的Address,傳入後,發現它複製了一份o指標,m所指的位置並不是o,接著把m所指向的值由1048改為1168 ( *m = @"Modify"),到目前為止都懂,奇妙的是原本o所存儲的值也跟著變了,藉由這個方式,可以在方法中修改原先傳入的指標的存儲值,使他指向新的物件。不過我疑惑的是,為什麼修改的是m所指向的值,o卻也跟著改變,這個我尚未明白,請高手指點明燈。
指標 Pointer
int main(int argc, const char * argv[]) { @autoreleasepool { NSString * ptr = @"Content"; NSLog(@"The value of ptr : %p",ptr); NSLog(@"The address of @\"Content\" : %p",@"Content"); NSLog(@"The address of ptr : %p",&ptr); } return 0; }
我們先來看這一行,NSString * ptr = @"Content"; ,這裡宣告了一個指標ptr,指向一個NSString的物件,而這個物件的值是@"Content",數值於電腦運算時,都存儲於記憶體中,可以想成一條馬路上有許多房子,大小固定,都有門牌,而物件有大有小,有些可能需要好幾間房子打通才放得下。示意圖如下,Ptr所存的值( 0x100001040 )剛好是這個字串的記憶體位置,ptr本身也有個Address是 0x7fff5fbff898。由這個例子可以知道要知道門牌位置必須使用 & 取址運算子,在NSLog中用%p列印出來。
那你也可能會問,ptr這個指標名稱又是存在哪裡了,應該也需要一塊記憶體去記錄吧!!沒錯,它在編譯執行後,作業系統記錄了它的名稱與Address,當你需要用ptr時,系統去找有沒有ptr這個東西,有的話又在記憶體的哪裡,這個你沒有辦法操作,也遠離了今天的主題,所以我們暫不討論。
&取址運算子,告訴我這個變數的記憶體位置。
*取值運算子,告訴我這個變數所指過去的物件值是什麼。
現在可以來看看方法參數的傳遞是如何運作的:
#import <Foundation/Foundation.h> void someOperate(NSString *m); int main(int argc, const char * argv[]) { @autoreleasepool { NSString *o = @"Origin"; NSLog(@"The address of o : %p",&o); NSLog(@"The value of o : %p",o); NSLog(@"The address of @\"Origin\" : %p",@"Origin"); someOperate(o); NSLog(@"%@",o); NSLog(@"The address of o : %p",&o); NSLog(@"The value of 0 : %p",o); } return 0; } void someOperate(NSString *m) { NSLog(@"**********"); NSLog(@"The address of m : %p",&m); NSLog(@"The value of m :%p",m); m = @"Modify"; NSLog(@"After"); NSLog(@"The address of m : %p",&m); NSLog(@"The value of m :%p",m); NSLog(@"The address of @\"Modify\" : %p",@"Modify"); NSLog(@"**********"); }
那如果我們想要的是直接更改原本的值,該怎麼做呢。有幾種方法,先講最容易的,把NSString改為NSMutableString,這樣在改值時,就會把原先的值,在原位置直接改變,而不是新產生一個新的物件。
#import <Foundation/Foundation.h> void someOperate(NSMutableString *m); int main(int argc, const char * argv[]) { @autoreleasepool { NSMutableString *o = [[NSMutableString alloc]initWithString:@"Origin"]; NSLog(@"The address of o : %p",&o); NSLog(@"The value of o : %p",o); someOperate(o); NSLog(@"%@",o); NSLog(@"The address of o : %p",&o); NSLog(@"The value of 0 : %p",o); } return 0; } void someOperate(NSMutableString *m) { NSLog(@"**********"); NSLog(@"The address of m : %p",&m); NSLog(@"The value of m :%p",m); [m setString:@"Modify"]; NSLog(@"After"); NSLog(@"The address of m : %p",&m); NSLog(@"The value of m :%p",m); NSLog(@"**********"); }但是如果沒有辦法更改為Mutable的類別時該怎麼辦,這時候有個迂迴的用法,指標的指標,既然無法更動指標所指的值,那就變動指標所存儲的記憶體Address,看一段代碼。
#import <Foundation/Foundation.h> void someOperate(NSString **m); int main(int argc, const char * argv[]) { @autoreleasepool { NSString *o = @"Origin"; NSLog(@"The address of o : %p",&o); NSLog(@"The value of o : %p",o); NSLog(@"The address of @\"Origin\" : %p",@"Origin"); someOperate(&o); NSLog(@"%@",o); NSLog(@"The address of o : %p",&o); NSLog(@"The value of o : %p",o); } return 0; } void someOperate(NSString **m) { NSLog(@"**********"); NSLog(@"The address of m : %p",&m); NSLog(@"The value of m :%p",m); NSLog(@"The value of *m : %p",*m); *m = @"Modify"; NSLog(@"After"); NSLog(@"The value of *m : %p",*m); NSLog(@"The address of m : %p",&m); NSLog(@"The value of m :%p",m); NSLog(@"The address of @\"Modify\" : %p",@"Modify"); NSLog(@"**********"); }
這邊宣告一個變數o指向@"Origin",o的記憶體位置是f898,o的值是1048,也就是@"Origin"的記憶體位置,someOperate方法接受的參數為指標的指標,而也就是o指標的Address,傳入後,發現它複製了一份o指標,m所指的位置並不是o,接著把m所指向的值由1048改為1168 ( *m = @"Modify"),到目前為止都懂,奇妙的是原本o所存儲的值也跟著變了,藉由這個方式,可以在方法中修改原先傳入的指標的存儲值,使他指向新的物件。不過我疑惑的是,為什麼修改的是m所指向的值,o卻也跟著改變,這個我尚未明白,請高手指點明燈。
標籤:
objective-c
訂閱:
文章 (Atom)