复制还会转移保留计数吗?

时间:2013-09-17 21:33:46

标签: objective-c memory-management

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

6 个答案:

答案 0 :(得分:5)

这取决于。 copycopyWithZone:的便捷方法, 以及"NSCopying Protocol Reference"州:

  

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

     
      
  • 使用NSCopyingalloc在不支持的类中实施init...   继承copyWithZone:
  •   
  • 通过调用实现NSCopying   当继承copyWithZone:行为时,超类的NSCopying。如果   超类实现可能使用NSCopyObject函数,   对保留的指针实例变量进行显式赋值   对象。
  •   
  • 通过保留原始内容而非实施NSCopying   在类及其内容不可变时创建新副本。
  •   

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

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

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

但你不应该关心这种差异。通过手动引用计数,  copy会返回您拥有的对象,并且最终必须发布。 使用ARC,编译器可以自动处理。

答案 1 :(得分:5)

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

没关系。

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

重要的是,如果要将对象放回系统,必须在某处保持releaseautorelease。这实际上可能不会导致其被解除分配;这是一个无关紧要的实现细节(无论如何,直到优化时间)。

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

对于不可变对象,copy方法可以简单地实现为return [self retain];。或者,在静态NSStrings(NSCFStrings)的情况下,它可能只是return self;,因为retain / release / autorelease对这些字符串是no-ops。

答案 2 :(得分:4)

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

如果您想了解更多信息,我强烈建议您阅读Memory Management Guide

如果您是iOS开发的新手,应首先阅读iOS App Programming Guide,并充分利用您的时间。

我刚刚注意到您没有将此标记为特定于iOS,如果您为Mac编码,Programming with Objective-C指南可能更适合您。

答案 3 :(得分:1)

为了真正理解这个问题,不要考虑保留计数,考虑指针所有权(如ARC所做的那样)。

如果一个对象的“保留计数”为5,这意味着某处的五个代码各自都有一个指向其内存地址的(强)指针。如果您copy该对象,则会获得指向新复制对象的地址的指针。其他五段代码仍然指向原始对象。只有一段代码指向新对象,因此它的“保留计数”是一个。

正如其他答案所述,Memory Management Guide肯定有助于明确这一点。

为什么我将“保留计数”放在引号中?因为它只是作为一般概念有用 - 你不应该直接使用retainCount,否则你会听到@bbum。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

当你要求它复制对象时,Objective-C会发挥一些聪明的技巧,因此保留计数可能不是你认为的那样。

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

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

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

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