1

假设我有一个对象,例如一个 NSString,保留计数为 5。当我调用它的副本时,我得到了该对象的一个​​新副本;这个新对象是否具有其原始对象的保留计数?

4

6 回答 6

5

copy返回一个对象,它是对象的语义 [浅] 副本(1)。该copy方法返回的是一个实现细节;它可能返回相同的对象,可能返回同一类的不同实例,甚至可能返回不同类的实例。

没关系。

重要的是,在手动保留/释放下,返回的对象的保留计数为 +1。不是1,而是+1。它实际上可能是 1、42、981 或 -1。没关系。

重要的是,如果您想将对象交还给系统,则必须平衡保留与 arelease或某处。autorelease这实际上可能不会导致它被释放;这是一个无关紧要的实现细节(无论如何,直到优化时间)。

(1)语义[shallow] copy表示返回的对象是有效的浅拷贝。当原始对象更改状态时,复制对象中包含的状态(但不在对象中包含的对象中 - 即浅部分)不会改变。对于可变对象,copy必须实际创建某个对象的新实例——很可能是不可变的变体类——它可以包含原始状态。

对于不可变对象,该copy方法可以简单地实现为return [self retain];. 或者,在静态 NSStrings ( NSCFStrings) 的情况下,它可能只是return self;因为保留/释放/自动释放对此类字符串是无操作的。

于 2013-09-17T23:48:57.173 回答
5

这取决于。copy是一种方便的方法copyWithZone:,并且“NSCopying 协议参考”指出:

您实现此协议的选项如下:

  • 在不继承 copyWithZone: 的类中 实现NSCopyingusing allocand 。init...
  • 通过在继承行为时NSCopying调用超类来实现。如果超类实现可能使用该函数,则为保留对象显式分配指针实例变量。 copyWithZone:NSCopyingNSCopyObject
  • NSCopying当类及其内容不可变时,通过保留原始副本而不是创建新副本来实现。

(在所有反馈之后,我修改了以下两个语句。)

例如,NSString是一个不可变对象,并且copy只是保留该对象并返回指向同一对象的指针。保留对象可能会增加保留计数,但不一定(如字符串文字的情况。)

复制一个NSMutableString可能会创建一个新对象并返回它。新对象将有自己的保留计数,独立于原始对象。

但是你不应该关心差异。使用手动引用计数, copy返回一个您拥有并最终必须释放的对象。使用 ARC,编译器会自动处理它。

于 2013-09-17T21:42:59.730 回答
4

不,复制的对象的保留计数为 1,就像新初始化的对象一样。

如果您想了解更多信息,我强烈建议您阅读内存管理指南。

如果您是 iOS 开发新手,应该先阅读iOS 应用程序编程指南,它可以很好地利用您的时间。

我刚刚注意到您没有将此标记为特定于 iOS,如果您正在为 Mac 编码,那么使用 Objective-C 编程指南可能更适合您。

于 2013-09-17T21:38:52.087 回答
2

要真正解决这个问题,不要考虑保留计数,考虑指针所有权(就像 ARC 一样)。

如果一个对象的“保留计数”为 5,这意味着某处的五段代码各自持有一个指向其内存地址的(强)指针。如果你copy是那个对象,你会得到一个指向新的、复制的对象的地址的指针。其他五段代码仍然指向原始对象。只有一段代码指向新对象,所以它的“保留计数”是一。

正如其他答案中所述,内存管理指南肯定有助于使这一切变得清晰。

为什么我将“保留计数”放在引号中?因为它仅作为一般概念有用——您不应该retainCount直接使用,否则您会收到@bbum 的消息。

于 2013-09-17T21:49:13.817 回答
1

当您要求 Objective-C 复制对象时,Objective-C 会使用一些巧妙的技巧,因此保留计数可能不是您认为应该的那样。

假设您有一个保留计数为 n 的对象指针 x,并调用返回对象指针 y 的复制方法。

NSObject* x = ...; 
NSObject* y = [x copy];

那么规则是,如果你释放 xn 次,释放 y 一次,所有的对象都会消失。通常这是通过保持 x 不变并给 ya 保留计数 1 来实现的。

但是,如果 x 指向一个不可变对象,那么 Objective-C 可能会决定不需要进行复制。结果是 y = x。尽管如此,上面的规则仍然适用:释放 xn 次和 y 一次(即使它们是同一个对象)将释放所有涉及的对象。这是通过返回带有 +1 保留计数的 x 的复制方法来实现的。

于 2014-08-08T00:38:01.203 回答
0

复制像 NSMutableArray 这样的可变对象将创建一个新副本,并且保留计数将为 1,而像 NSArray 这样的复制不可变对象将指向相同的引用并将保留计数增加 1。

于 2014-08-07T23:50:19.490 回答