不可变实例、可变实例、copy与mutableCopy
代码:
#import <Foundation/Foundation.h> // 本例中 // 将诸如NSString、NSDictionary等类的实例称为不可变实例 // 将诸如NSMutableString、NSMutableDictionary等类的实例称为可变实例 // 不论这个实例是不可变实例还是可变实例 // 调用该实例的opy方法,得到的实例是不可变实例 // 调用该实例的mutableCopy方法,得到的实例是可变实例 // 在非ARC环境下 // 通过向实例发送copy或mutableCopy消息得到的实例需要手工调用release或autorelease方法 void stringCopy(void); void stringMutableCopy(void); void mutableStringCopy(void); void mutableStringMutableCopy(void); int main(int argc, const char * argv[]) { stringCopy(); stringMutableCopy(); mutableStringCopy(); mutableStringMutableCopy(); return 0; } void stringCopy(void) { NSLog(@"NSString copy:"); NSString *stringA = [[NSString alloc] initWithFormat:@"Objective-C"]; // 对于不可变实例而言,向其发送一条copy消息,返回的实例依然是不可变实例,并且就是原不可变实例本身 // 该复制方式称为浅复制 NSString *stringB = stringA.copy; // 原不可变实例的引用计数器的值加1 // 从copy消息返回的不可变实例的引用计数器的值与原不可变实例的引用计数器的值加1后的值相同 NSLog(@"Address(stringA) = %p, retainCount(stringA) = %lu", stringA, stringA.retainCount); NSLog(@"Address(stringB) = %p, retainCount(stringA) = %lu", stringB, stringB.retainCount); // 原不可变实例的指针与从copy消息返回的不可变实例的指针相同,指向同一块内存区域 NSLog(@"Address(stringA) == Address(stringB): %@", stringA == stringB ? @"YES" : @"NO"); [stringA release]; [stringB release]; } void stringMutableCopy(void) { NSLog(@"NSString mutableCopy:"); NSString *stringA = [[NSString alloc] initWithFormat:@"Objective-C"]; // 对于不可变实例而言,向其发送一条mutableCopy消息,返回的实例是一个新的可变实例 // 该复制方式称为深复制 NSMutableString *stringB = stringA.mutableCopy; // 原不可变实例的引用计数器值不变 NSLog(@"Address(stringA) = %p, retainCount(stringA) = %lu", stringA, stringA.retainCount); // 从mutableCopy消息返回的新的可变实例的引用计数器为1 NSLog(@"Address(stringB) = %p, retainCount(stringA) = %lu", stringB, stringB.retainCount); // 原不可变实例的指针与从copy消息返回的可变实例的指针不同,不指向同一块内存区域 NSLog(@"Address(stringA) == Address(stringB): %@", stringA == stringB ? @"YES" : @"NO"); [stringA release]; [stringB release]; } void mutableStringCopy(void) { NSLog(@"NSMutableString copy:"); NSMutableString *stringA = [[NSMutableString alloc] initWithFormat:@"Objective-C"]; // 对于可变实例而言,向其发送一条copy消息,返回的实例是一个新的不可变实例 // 该复制方式称为深复制 NSString *stringB = stringA.copy; // 原可变实例的引用计数器的值不变 NSLog(@"Address(stringA) = %p, retainCount(stringA) = %lu", stringA, stringA.retainCount); // 从mutableCopy消息返回的新的可变实例的引用计数器为1 NSLog(@"Address(stringB) = %p, retainCount(stringA) = %lu", stringB, stringB.retainCount); // 原可变实例的指针与从copy消息返回的不可变实例的指针不同,不指向同一块内存区域 NSLog(@"Address(stringA) == Address(stringB): %@", stringA == stringB ? @"YES" : @"NO"); [stringA release]; [stringB release]; } void mutableStringMutableCopy(void) { NSLog(@"NSMutableString mutableCopy:"); NSMutableString *stringA = [[NSMutableString alloc] initWithFormat:@"Objective-C"]; // 对于可变实例而言,向其发送一条mutableCopy消息,返回的实例是一个新的不可变实例 // 该复制方式称为深复制 NSMutableString *stringB = stringA.mutableCopy; // 原可变实例的引用计数器的值不变 NSLog(@"Address(stringA) = %p, retainCount(stringA) = %lu", stringA, stringA.retainCount); // 从mutableCopy消息返回的新的可变实例的引用计数器为1 NSLog(@"Address(stringB) = %p, retainCount(stringA) = %lu", stringB, stringB.retainCount); // 原可变实例的指针与从mutableCopy消息返回的可变实例的指针不同,不指向同一块内存区域 NSLog(@"Address(stringA) == Address(stringB): %@", stringA == stringB ? @"YES" : @"NO"); [stringA release]; [stringB release]; }
输出:
NSString copy: Address(stringA) = 0x100106800, retainCount(stringA) = 2 Address(stringB) = 0x100106800, retainCount(stringA) = 2 Address(stringA) == Address(stringB): YES NSString mutableCopy: Address(stringA) = 0x100106800, retainCount(stringA) = 1 Address(stringB) = 0x10010e1a0, retainCount(stringA) = 1 Address(stringA) == Address(stringB): NO NSMutableString copy: Address(stringA) = 0x10010e290, retainCount(stringA) = 1 Address(stringB) = 0x10010e1e0, retainCount(stringA) = 1 Address(stringA) == Address(stringB): NO NSMutableString mutableCopy: Address(stringA) = 0x10010e290, retainCount(stringA) = 1 Address(stringB) = 0x10010e2f0, retainCount(stringA) = 1 Address(stringA) == Address(stringB): NO
豪情壮志铁傲骨,原来英雄是孤独。