首先,从内存管理层面看:
普通对象都是存储到堆内存上,而对于NSString对象:
NSString 初始化方法的内存方式比较
NSString *str1 = @"hello";
NSString *str2 = @"hello";
NSString *str3 = [NSString stringWithFormat:@"hello"];
NSString *str4 = [NSString stringWithString:@"hello"];
NSString *str5 = [[NSString alloc]initWithString:@"hello"];
NSLog(@"%p //%p //%p // %p //%p",str1,str2,str3,str4,str4,str5);
0x92a88 //0x92a88 //0x796b96b0 // 0x92a88 //0x92a88
SSting的对象在使用@"xx"直接初始化赋值时,它会在常量中分配一个空间,用于保存该变量。
(即存储在内存里的常量区而非堆区)
相同赋值的对象,会采用相同的内存空间,表现为内存地址相同。
可以理解为NSString的isa的值是一样的。
NSString *str2=@"e中国2";
NSString *str3=@"e中国2";
// %p for pointers to show the memory address
NSLog(@"str2'addr is %p str3'addr is %p",str2,str3);
使用stringWithFormat:工厂方法初始化NSString对象时,每次都独立分配内存空间。
这个空间是在堆区中,而不是常量区中。
即使相同内容的NSString对象,通过%d获取的对象的内存地址的值不一致。
NSString *str2=[NSString stringWithFormat:@"e中国%i",2];
NSString *str3=[NSString stringWithFormat:@"e中国%i",2];
// %p for pointers to show the memory address
NSLog(@"str2'addr is %p str3'addr is %p",str2,str3);
NSString的比较方法,比较内容应该是isEqualToString:,比较指针的是==比较符号。通常情况下,你需要比较的都会是内容本身而不是其指针值
copy和mutable copy
1. copy出来的字符串一定是不可变字符串,如果传入的是可变字符串,会发生深拷贝为不可变字符串,否则为浅拷贝。
2. mutablecopy,一定是深拷贝,拷贝出来的一定是可变字符串或者数组,即使传入的是不可变字符串或者数组。
拓展:copy与mutableCopy对比
总的来说:
NSString *string = @"origion";
NSString *stringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
[stringMCopy appendString:@"!!"];
上面这段代码中,需要注意的点:
1. retainCount对常量是无效的,数字会是个很大的数字。它对堆上的内存对象是正确的,对于 栈上的常量无效。
2. copy指的是浅复制,只是复制指针。(对可变的集合而言,copy是生成一个不可变对象。对 不可变的集合而言,copy等于strong,其中的元素都是浅拷贝)
3. mutableCopy是深复制,复制了对象到新的内存空间(对集合而言,mutableCopy是生成一个新的可变对象,其中的元素都是浅拷贝)
4. mutableCopy出来的都是可变的(如NSMutableString)