NSLog(@"global string address -- %p",g_test);// g_test为全局string
NSString*str =@"this is a str on stack.";
NSLog(@"local string address -- %p", str);
NSString*str_ = [NSString stringWithFormat:@"this is a str on heap."];
NSLog(@"heap string address -- %p", str_);
NSString*str__ =@"this is a str on stack.";
NSLog(@"text string address -- %p", str__);
输出结果:
可以看出:
1.使用字面值常量初始化的字符串对象使用了享元模式,同样的字面值常量在栈上使用同一块内存。
2.使用stringWithFormat:初始化的字符串对象内存分配在堆上,需要注意在反复调用的函数内内使用该种方式初始化的字符串会引起内存的快速增长,并且没有被释放,当显式地使用
@autorelease{ NSMutableString*string = [NSMutable StringstringWithFormat:@"this is a local variable"]; }
时,内存没有出现快速的增长。一些关于分析autoreleasepool原理的博客中描述,stringWithFormat:中自动将string对象放进了自动释放池,当定义区域的生命周期结束,会将自动释放池中的对应的内存标记为需要释放,等待下一个runloop循环释放掉已经标记的内存,在当前版本下的实验并非如此。由于前面的问题,猜想可能是NSString or autorelease的实现有变化导致。
当使用NSString作为类成员属性时,使用strong 还是 copy 关键字?
1.通常情况下会使用copy。
2.使用strong的时候需要注意该成员在生命周期内被修改时存在的风险。
当使用一个NSMutableString 对象对NSString 对象初始化的时候:
@property (nonatomic, strong) NSString* test;
test 指向 NSMutableString 对象在堆上分配的内存的首地址,当该可变字符串在其他地方被修改的时候,test指向的内容也随着发生了变化(test所指向的内存的类型信息是NSMutableString,所以test的值是当前完整的NSMutableString 对象的值),test的值发生了超出我们预料的改变。当然,也可以是设计这么使用。
@property (nonatomic, copy) NSString* test_;
NSMutableString 对象会拷贝当前的内容,并开辟一块新的内存空间,test_指向新的内存空间,新的内存空间类型信息为NSString,转变为不可变字符串。
3. 补充说明:(copy属性在类内需要使用self.property来赋值)值copy是在set方法中进行