在以下示例中,stringWithString:(NSString *)
是否将theName
的内存地址/位置复制到name
,或者它实际上将数据从theName
复制到name
?
@interface AddressCard:NSObject
-(void)setName:(NSString *)theName;
@end
@implementation AddressCard
NSString *name;
-(void)setName:(NSString *)theName
{
if(name!=theName)
name = [NSString stringWithString:theName];
}
@end
如果我将代码更改为以下代码,那么copy
做了哪些不同的事情?
@interface AddressCard:NSObject
@property (copy, nonatomic) NSString *name;
@end
@implementation AddressCard
@synthesize name;
@end
通常,copy
(@property
属性)是否复制数据的地址或将数据从一个变量复制到另一个变量?如果是后一种情况,当变量代表大数据时,我们不会消耗大量内存吗?
感谢您的时间和回应!
答案 0 :(得分:2)
stringWithString将创建一个副本if it's mutable。但要注意since it's not alloc, init, copy方法,它是自动释放的。您现在持有的副本将在该set方法退出后的某个时刻点亮。如果你改为使用initWithString,它也会创建另一个字符串但保留它。
复制属性意味着在将复制消息发送到传入的对象后,将为该属性分配返回的对象。这意味着由该对象类型决定它如何处理副本。对于您的特定字符串示例,(copy)将创建一个字符串的副本返回给调用者 - 保留的副本。由调用者释放保留的对象。根据{{3}},副本将保留对象。
答案 1 :(得分:2)
+[NSString stringWithString:]
将有效地'复制'字符串。
一般来说,复制(@property属性)是复制数据的地址还是将数据从一个变量复制到另一个变量?
它执行对象认为是copy
的任何内容。它可能会返回一个新对象,也可能会返回它自己。例如,如果参数已经是不可变的,+[NSString stringWithString:]
可以只返回保留的参数并自动释放。如果参数是可变的,那么它将返回一个新实例,因此保证你有一个不可变的实例。
啊哈 - 但这就是诀窍!是的,你最终可能会使用副本进行许多新的分配,但是当你喜欢不可变类型并使用如果是后一种情况,当变量代表大数据时,我们不会消耗大量内存吗?
copy
时,通常情况下,引用计数对象的副本通常非常浅。如果它们已经是不可变的,许多集合类型可以简单地返回它们,或者它们的ivars可以这样做,所以确保你不会传递可变对象实际上是一个非常好的主意 - 所以尽早创建一个不可变的副本确实允许这个优化传播,并为您节省大量的分配(但并非总是如此 - 所有这些变种都有许多极端情况)。
注意:并非所有类都将不变性与可变性区分开来,因此副本并不总是返回不可变对象。