NSString *str = [NSString stringWithString:[[NSString alloc] initWithFormat:@"123"]]; int i= [str retainCount]; //2 方法中套init,套用的init不会自动release NSString *str2 = [[NSString alloc] initWithFormat:[[NSString alloc] initWithFormat:@"456"]]; int i2= [str2 retainCount]; //1 重新分配内存
总结:最好不在在调用方法中套用init,可以使用autorelease.
NSString *str = [[NSString alloc] initWithFormat:@"123"]; NSString *str2 = str;
[str release]; str = @"23"; int i = [str retainCount]; //-1, str为 int i2 = [str2 retainCount]; //1, str2为"123"
总结:NSString* 应该指向是常量区,所以str在再赋值为"23"前是否release,结果都是上面。猜想是因为常量区的内存不会被回收.
所以非copy属性的NSString* 再被赋值前不需要release,也可以release,赋值后可以调用retain,也可以不调用。
但是alloc的NSString*一定要记得 release.
非copy属性的NSString*或者NSMutableString*=赋值是不会调用retain的.
以下为错误的:
NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"123"]; NSMutableString *str2 = str; int i3 = [str2 retainCount]; //1 [str release]; //内存被释放了 str = @"23"; int i = [str retainCount]; //-1 str为"23" int i2 = [str2 retainCount]; //1 str2为nil, 为什么此处str2不为0,猜想是因为 str2不为nil,指针仍指仍指向某块内存,retainCount计算的是指针指向对象的拥有者的个数.
总结:NSMutableString* 应该指向是分配的内存,所以str在再赋值为"23"前release,内存被回收. str2成为野指针了。会很容易出错的,到时会没法回收啊。必须置为nil.
所以NSMutablesString*在被赋值后需要调用retain,在再赋值前需要release。临时的NSString*或NSMutableString*对象被赋值都不会调用retain.
正确的应该为
NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"123"]; NSMutableString *str2 = str; [str2 retain]; int i3 = [str retainCount]; [str release]; str = @"23"; int i = [str retainCount]; //-1 int i2 = [str2 retainCount]; //1 str2 为"123"
关于retainCount:
NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"123"]; NSMutableString *str2 = str; [str2 retain]; int i = [str2 retainCount]; //2 [str release]; int i2 = [str2 retainCount]; //1 int i3 = [str retainCount]; //1,因为此时str仍然指向的是"123", "123"的引用个数为1,即str2指向它,疑问:和前面的str2为nil的有点冲突哈 str = nil; int i4 = [str2 retainCount]; //1 int i5 = [str retainCount]; //0
关于属性为copy的NSString*和NSMutableString*的赋值
@property(copy, nonatomic)NSString *str2; //NSSting* copy赋值会retain
NSString *str = [[NSString alloc] initWithFormat:@"123"]; self.str2 = str; //对于str NSString, 相当于是retain,共享同一个内存, 如果使用str2 = str,则不会使用copy属性。 int i2 = [self.str2 retainCount]; //2 int i = [str retainCount]; //2 str = @"567"; i2 = [self.str2 retainCount]; //2 str2为"123",因为str没有release i = [str retainCount]; //-1 str为"567"
如果str在再赋值前[str release];则:
@property(copy, nonatomic)NSString *str2; //NSSting* copy赋值会retain NSString *str = [[NSString alloc] initWithFormat:@"123"]; self.str2 = str; //对于str NSString, 相当于是retain,共享同一个内存 int i2 = [self.str2 retainCount]; //2 int i = [str retainCount]; //2 [str release]; str = @"567"; i2 = [self.str2 retainCount]; //1 str2为"123" i = [str retainCount]; //1 str为"567"
@property(copy, nonatomic)NSMutableString *str2;
NSMutableString *str = [[NSMutableString alloc] initWithFormat:@"123"]; self.str2 = str; //对于NSMutableString,会重新分配内存,copy为不可变副本 NSMutableString *str3 = str2; int i2 = [self.str2 retainCount]; //1 int i = [str retainCount]; //1 self.str2 = @"567"; i = [str retainCount]; //1 i2 = [self.str2 retainCount]; //-1 int i3 = [str3 retainCount]; //1 说明str2分配的内存并没有释放
以上总结都是废话,以下为最后的总结:
1. 千万不在在调用方法中套用init
2. alloc一定要 release,再赋值
3. 默认的 NSString*或NSMutableString*是assign属性的,assign赋值不会调用retain.
4. copy对于NSString*来说是retain计数+1,对于NSMutableString*来说是alloc,都要release 再赋值,如果你不想被其它指针修改指向的内存就用这个吧。
5. =赋值是不会自动调用release的.
6. 最好使用retain属性,否则如果内存被释放掉,你就成了野指针的。
7. release后,请设为nil.
xcode中的ARC机制的strong就是替代了retain和release动作.
ARC中的weak替代了assign和设为nil操作,如果内存被释放掉了,会自动将weak的对象置为nil,不会出现野指针的错误。
所以如果你不想在当前指针操作内存的这段时间内内存被释放掉,请一定要在赋值时使用retain和release,或者copy。
如果你的目的是在这块内存的生命周期内,暂时的操作这块内存,当前指针的生命周期一定会小于内存的生命周期,可以使用assign.
NSMutableString *str = [[NSMutableString alloc] initWithString:@"123"]; int i = [str retainCount];//1 NSArray *array = [[NSArray alloc] initWithObjects:str, nil]; int i2 = [str retainCount];//2 addObject也会执行retain动作 [array release]; int i3 = [str retainCount];//1 array release的同时,元素也会执行release动作