思考
一言不合先上個(gè)小小的思考吧
NSString *str0 = @"1";
NSString *str1 = [NSString stringWithFormat:@"1"];//
NSLog(@"%d", str0 == str1);
NSLog(@"%d", [str0 isEqualToString:str1]);
NSLog(@"%d", [str0 isEqual:str1]);
大家可以短暫的思索下輸出的結(jié)果脾拆,后面我們?cè)僬f
關(guān)于NSString內(nèi)存
帶著測(cè)試來看吧
NSString *str0 = @"1";
NSString *str1 = [NSString stringWithFormat:@"1"];//
NSString *str2 = [[NSString alloc] initWithString:@"1"];//
NSMutableString *str3 = [[NSMutableString alloc] initWithString:@"1"];//
NSString *strs0copy = str0.copy;
NSString *str3copy = str3.copy;
NSString *str0mucopy = str0.mutableCopy;
NSString *str00mucopy = str0.mutableCopy;
NSLog(@"str0:%p", str0);
NSLog(@"str1:%p", str1);
NSLog(@"str2:%p", str2);
NSLog(@"strs0copy:%p", strs0copy);
NSLog(@"str3:%p", str3);
NSLog(@"str3copy:%p", str3copy);
NSLog(@"str0mucopy:%p", str0mucopy);
NSLog(@"str00mucopy:%p", str00mucopy);
我們看下輸出的結(jié)果以及堆棧信息
2017-06-08 15:50:52.198 NSString_ memory[68403:4037182] str0:0x103513068
2017-06-08 15:50:52.199 NSString_ memory[68403:4037182] str1:0xa000000000000311
2017-06-08 15:50:52.199 NSString_ memory[68403:4037182] str2:0x103513068
2017-06-08 15:50:52.199 NSString_ memory[68403:4037182] strs0copy:0x103513068
2017-06-08 15:50:52.199 NSString_ memory[68403:4037182] str3:0x618000263c00
2017-06-08 15:50:52.199 NSString_ memory[68403:4037182] str3copy:0xa000000000000311
2017-06-08 15:50:52.199 NSString_ memory[68403:4037182] str0mucopy:0x618000263bc0
2017-06-08 15:50:52.200 NSString_ memory[68403:4037182] str00mucopy:0x618000263b80
堆棧信息
上面我們看出str0、str2下翎、strs0copy的內(nèi)存地址是一樣的
str1和str3copy是一樣的
堆棧信息告訴我們str0混稽、str2采驻、strs0copy的類型是__NSCFConstantString审胚;字符串常量存儲(chǔ)區(qū),字面量相等的共用一塊常量存儲(chǔ)地址匈勋,常量區(qū)的copy操作是淺拷貝依然相同地址
對(duì)于str2的寫法,編譯器會(huì)報(bào)一警告,警告我們str2的字面量賦值是多余的膳叨,默認(rèn)會(huì)給我們str0的形式,str2依然是在常量區(qū)洽洁;
str1和str3copy的類型是NSTaggedPointerString,跟字面量的值密切相關(guān)菲嘴,是在棧上
其余的str3饿自、str0mucopy、str00mucopy則是__NSCFString,堆分配
關(guān)于NSTaggedPointerString的解釋參考
【譯】采用Tagged Pointer的字符串
深入理解Tagged Pointer
isEqualToString龄坪、isEqual
isEqual比較兩個(gè)兩個(gè)對(duì)象是否相等
來看下isEqual的源碼
- (BOOL)isEqual:(id)obj {
return obj == self;
}
回過頭昭雌,我們看開頭的輸出結(jié)果分別是0、1健田、1烛卧,既然str0和str1的內(nèi)存地址是不一樣的,那為什么isEqual會(huì)相等呢妓局,那就是NSString內(nèi)部重寫了isEqual总放,雖然拿不到官方的源碼,我們可以看下GNUstep Base源碼一定程度可以作為一個(gè)參考
- (BOOL) isEqual: (id)anObject
{
if (anObject == self)
{
return YES;
}
if (anObject != nil && [anObject isKindOfClass: NSStringClass])
{
return [self isEqualToString: anObject];
}
return NO;
}
內(nèi)存不等的情況下比較的說isEqualToString好爬,這樣我們就明白了
我們?cè)倏聪耰sEqualToString
- (BOOL) isEqualToString: (NSString*)aString
{
if (aString == self)
{
return YES;
}
if ([self hash] != [aString hash])
{
return NO;
}
if (strCompNsNs(self, aString, 0, (NSRange){0, [self length]})
== NSOrderedSame)
{
return YES;
}
return NO;
}
首先是否相等比較局雄,然后比較hash值,最后比較字面量是否相同存炮。
至此回到開頭我們蕩然于胸了炬搭。
當(dāng)然對(duì)于我們自定義對(duì)象的比較可以重寫- (BOOL) isEqual:和- (NSUInteger)hash蜈漓,當(dāng)然這里就不展開balabala了
后記
以上也是隨手看某一源碼隨手細(xì)致的琢磨了下,有不同見解的歡迎指出宫盔,生命在于折騰尤其在我大天朝=迎变。=