2

在下面的示例中,是复制tostringWithString:(NSString *)的内存地址/位置还是实际上将数据复制到to ?theNamenametheNamename

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

感谢您的时间和回复!

4

2 回答 2

2

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

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

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

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

啊哈-但这就是诀窍!是的,您最终可能会使用复制进行许多新分配,但诀窍通常是当您喜欢不可变类型并使用copy. 如果集合类型已经是不可变的,或者它们的 ivars 可能会这样做,许多集合类型可以简单地返回自己,因此确保您不传递可变对象实际上是一个非常好的主意——因此尽早创建不可变副本确实可以传播这种优化,并为您节省大量分配(但并非总是如此——所有这些变体都有许多极端情况)。

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

于 2012-08-25T13:44:47.773 回答
2

如果 stringWithString 是 mutable ,它将创建一个副本。但请注意,因为它不是自动释放的分配、初始化、复制方法。您现在持有的副本将在该 set 方法退出后的某个时间点消失。如果您改为使用 initWithString,它也会创建另一个字符串,但会保留它。

复制属性意味着属性将被分配在将复制消息发送到传入的对象后返回的对象。这意味着由该对象类型来确定它如何处理副本。对于您的特定字符串示例, (copy) 将创建字符串的副本返回给调用者 - 保留的副本。由调用者释放保留的对象。根据内存准则,复制将保留对象。

于 2012-08-25T13:36:25.817 回答