2012-08-25 36 views
2

在以下示例中,不stringWithString:(NSString *)theName存储器地址/位置复制到name或它实际上拷贝从theNamename数据?澄清@property属性

@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属性)从一个变量复制数据或拷贝数据的地址到另一个?如果是后一种情况,当变量代表大数据时,我们不会消耗大量内存吗?

谢谢您的时间和响应!

+3

我觉得你对于“拷贝”的作用感到困惑。它所做的只是向接收方发送“复制”消息,在某些情况下(不可变的'NSStrings或'NSData'),将只返回其自身的保留版本,因为没有任何可复制的东西。 –

+0

下面的答案有帮助吗? – bryanmac

+0

是的。他们非常有帮助。我对延迟承认表示歉意。 –

回答

2

+[NSString stringWithString:]将有效地 '复制' 的字符串。

一般来说,拷贝(@property属性)拷贝数据的地址还是拷贝数据从一个变量到另一个?

它执行任何对象认为是copy。它可能会返回一个新的对象,或者它可能会返回它自己。例如,+[NSString stringWithString:]可以只保留返回,如果参数已经是不可改变的自动释放参数。如果参数是可变的,那么它将返回一个新的实例,所以你保证有一个不可变的实例。

如果是后一种情况,当变量代表大数据时,我们是不是消耗大量内存?

啊哈 - 但是这招!是的,你最终可能会用副本做出许多新的分配,但诀窍经常是,当你喜欢不可变类型并使用copy时,在大多数情况下,引用计数对象的副本确实很浅。许多集合类型可以简单地返回自己,如果它们已经是不可变的,或者它们的ivars可以这样做的话,那么确保你没有传递可变对象实际上是一个好主意 - 所以尽早创建不可变副本确实可以传播这个优化,并为您节省大量的分配(但并非总是如此 - 对于所有这些变体,都会出现一些问题)。

注意:并非所有类都将不变性与可变性区分开来,因此副本并不总是返回不可变对象。

+2

+1有关可变与不可变的更深入的解释。这是关键。 – bryanmac

+0

@bryanmac干杯:) – justin

+0

@everybody:非常感谢您的回复。我对延迟承认表示歉意。 –

2

stringWithString将创建一个副本if it's mutable。但请注意since it's not alloc, init, copy方法是自动发布的。在set方法退出后,您现在持有的副本将在某个时间点变为poof。如果你改用initWithString,它会创建另一个字符串,但保留它。

副本属性指的属性将被分配的发送副本消息中传递的对象后返回的对象,这意味着它是由该对象类型来决定如何处理一个副本。对于特定的字符串示例,(副本)将创建一个字符串副本返回给调用者 - 保留副本。这取决于调用者释放保留的对象。根据memory guidelines,副本将保留该对象。

+0

非常感谢您的回复Bryanmac。我认为'stringWithString'是一个类方法,它可以初始化和创建对象。 如果您不介意,请您重新说明您的第二部分回复。我无法理解它。 –

+0

是的,stringWithString是一个类方法,将创建它,但看到我添加了链接的内存指导。它将被自动发布。复制消息将创建一个保留的对象。 – bryanmac

+1

请注意,如果传入的字符串是可变的,stringWithString实际上只会复制数据。否则,它将返回递增的retainCount版本的输入。 –