Code:
#import <Foundation/Foundation.h>
// 不论一个实例是不可变实例还是可变实例
// 通过向该实例发送copy消息,创建得到的实例是不可变实例
// 通过向该实例发送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];
}
Output:
NSString copy:
Address(stringA) = 0x100300270, retainCount(stringA) = 2
Address(stringB) = 0x100300270, retainCount(stringA) = 2
Address(stringA) == Address(stringB): YES
NSString mutableCopy:
Address(stringA) = 0x100400170, retainCount(stringA) = 1
Address(stringB) = 0x100400000, retainCount(stringA) = 1
Address(stringA) == Address(stringB): NO
NSMutableString copy:
Address(stringA) = 0x1001064a0, retainCount(stringA) = 1
Address(stringB) = 0x100106d70, retainCount(stringA) = 1
Address(stringA) == Address(stringB): NO
NSMutableString mutableCopy:
Address(stringA) = 0x100400000, retainCount(stringA) = 1
Address(stringB) = 0x100400250, retainCount(stringA) = 1
Address(stringA) == Address(stringB): NO