@“”字符串类型并释放您不拥有问题的对象
一个菜鸟问题。
如果我有一个字符串@“你好我是一个字符串”。 是@“”一个对象? 它是什么 ? 它存放在哪里?
如果我发布一个我没有创建的对象会发生什么? 或者它的复杂性是什么?
NSString *string1 = [[NSString alloc] initWithString:@"string"]; NSString *string2 = string1; [string2 release];
还有一个问题是什么区别?
NSString *string1 = [[NSString alloc] initWithString:@"string"]; NSString *string2 = @"string";
我知道我是一个菜鸟但我只是想知道。
提前致谢
编辑:
我的意思是说init initWithString而不是stringWithString
NSString *string2 = string1;
这不会创建新对象。 string1
不是对象,它是指向对象的指针。 该赋值只是复制指针并将其放在string2
。
由于实现细节( 内部实现细节在所有情况下可能都不是真的,永远不应该依赖 ),这是真的:
NSString *string1 = [NSString stringWithString:@"string"]; string1 == @"string"; // this is a true expression
字符串常量 – @“dddd” – 由编译器编译成二进制文件。 它们无法释放,每个唯一字符串只有一个常量。 stringWithString:
识别常量而不创建新副本。
现在,如果你这样做:
NSMutableString *string1 = [NSMutableString stringWithString:@"string"]; NSMutableString *string2 = string1; [string2 release];
这会将 @“string”复制到NSMutableString的新实例中,而string1将指向该对象。
但是,该代码将是一个过度释放( [string1 release];
也是),因为stringWithString:
返回一个自动释放的对象。
现在,如果你要:
NSMutableString *string1 = [[NSMutableString alloc] initWithString:@"string"]; NSMutableString *string2 = string1; [string2 release];
然后,就保留计数而言,该代码在技术上是正确的 ; 字符串对象将被释放。 但是在release
, string1
和string2
都是悬空指针 – 也就是说,它们所持有的地址不再指向可行的对象,并且尝试发送消息会产生未定义的结果。
永远不要释放您不拥有的对象。 规则很简单:如果您通过使用new
, alloc
, retain
或copy
(简称NARC)获得它,则只拥有一个对象。
通过任何其他方法获得的对象应返回自动释放。 这意味着该对象将在下一个自动释放池中自动释放。 如果要保留对象,则需要retain
它然后release
它。 如果您不关心在当前范围内使用完对象后是否取消分配对象,则不要对其执行任何操作。
所以,总结一下:
- 您必须将任何NARC与
release
配对 - 您不得将任何非NARC与
release
配对 - 非NARC方法将返回
autorelease
d对象 - 如果超出当前范围,则必须
retain
任何autorelease
d对象
解决您的具体问题:
-
@"Hello i am a string"
是一个对象。 它是NSConstantString
一个实例,它在编译时创建。 你不能也不应该release
它。 它将在应用程序的整个生命周期中继续存在。 看一下这个问题 ,了解更多相关信息。 - 如果您释放了一个您不拥有的对象,那么您将减少其保留计数,并且您将导致代码复杂化,假定它不能保留它。
当对象的所有者试图释放它并且它已经被释放时,释放你没有创建的对象最终会得到你和EXC_BAD_ACCESSexception。
关于你的第二个问题,这里有一个很好的讨论。
使用@""
语法时,您将创建一个对象。 它是创建不可变字符串的简写,也称为NSConstantString
。 字符串常量存储在应用程序二进制文件的数据段部分中,并与代码一起加载到内存中,并在运行时期间引用。
正如其他人所提到的,只要你没有为对象显式分配空间,就不应该释放它。 每当您过度释放对象时,您都会向应用程序引入意外的,通常是随机的问题。 @Radu的解释是现货。