從開始學的NSString *name=[[NSString alloc] init] 起,僅僅這句話是分配內存空間,一直在用,從來沒考慮過它的內部是怎么實現的。今天無意中看到了這一句代碼:
NSString *name = [NSString alloc]; NSLog(@"%p",name); name = [name init]; NSLog(@"%p",name);
試着打印了一下,發現兩個的內存地址不一樣:
alloc是開辟一個內存空間,init是初始化,為什么初始化不在原有的內存空間上初始化,而是重新開辟一個內存空間。於是開始查資料,這時又發現了一個新的迷惑:
NSObject *obj = [NSObject alloc]; NSLog(@"%p",obj); obj = [obj init]; NSLog(@"%p",obj);
打印結果:
怎么地址又變一樣了?再打印NSArray的試一試:
NSArray *person = [NSArray alloc]; NSLog(@"%p",person); person = [person init]; NSLog(@"%p",person);
再次打印結果:
仍然是不一樣的。原因是什么呢?首先看看NSStrng的init方法吧:
-(id)init{ if(self = [super init]) {// 重新賦值 //… } }
從代碼中可以分析,self=[super init]如果不為nil,就重新分配內存空間,這就解釋了為什么 NSString,NSArray的調用alloc]init]方法后,內存地址會不一樣,但是NSObject為什么會一樣呢,我們知道NSObject是一切類的基類,當[[NSString alloc]init]執行時,調用的[super init]就是 NSObject中的init方法,既然NSObject身為基類,它也就無法調用super init,所以當NSObject執行[[NSObject alloc]init]時,也就沒有了init重新分配空間這一環節。
至於蘋果公司為什么初始化一個實例要分兩步,個人認為是方便構造后初始化不同的方法,如果用 new關鍵字,只能調用一個init,而不能調用initWithName等方法。
知識拓展:
NSString alloc之后,沒有init,那么這部分alloc后的內存空間可不可以用?答案是顯而易見的,如果可以用,蘋果公司也就沒必要提供一個init方法,那么alloc后的指針稱為什么呢? 懸掛指針。
如果一個地方指針既不為空,也沒有被設置為指向一個已知的對象,則這樣的指針稱為懸掛指針。在程序里面是很危險的事。當程序運行使用該指針時,程序不能判斷指針的合法性,將會產生很嚴重的錯誤。
【掃描關注更多精彩內容】
微信公眾號:xiaoniu