这些陈述中的复制,保留和分配有什么区别?

时间:2013-10-14 13:53:13

标签: ios objective-c cocoa

我试图理解以下四种情况的内存管理之间的区别:

@implementation ABC

-(void) fun1 
{
   ObjectA * obj1 = [[ObjectA alloc] init];
   ObjectA * obj2 = obj1;
}

-(void) fun2 
{
   ObjectA * obj1 = [[ObjectA alloc] init];
   ObjectA * obj2 = [obj1 retain];
}

-(void) fun3 
{
   ObjectA * obj1 = [[ObjectA alloc] init];
   ObjectA * obj2 = [obj1 copy];
}

-(void) fun4
{
   ObjectA * obj1 = [[ObjectA alloc] init];
   ObjectA * obj2 = [obj1 mutableCopy];
}

@end

我咨询了this question,但我仍然不清楚上述各方面之间的差异。有人可以解释每个人做了什么,以及他们为什么不同?

2 个答案:

答案 0 :(得分:6)

我从retain的存在推断,你正在使用MRR(手动保留和释放)。在MRR中,此代码导致:

@implementation ABC

-(void) fun1 
{
   ObjectA * obj1 = [[ObjectA alloc] init];  // retainCount = +1
   ObjectA * obj2 = obj1;                    // unchanged

   // you have one instance of `ObjectA` with a retain count of +1
   // both `obj1` and `obj2` point to the same single instance
}

-(void) fun2 
{
   ObjectA * obj1 = [[ObjectA alloc] init];  // retainCount = +1
   ObjectA * obj2 = [obj1 retain];           // retainCount = +2

   // you have one instance of `ObjectA` with a retain count of +2
   // both `obj1` and `obj2` point to the same single instance
}

-(void) fun3 
{
   ObjectA * obj1 = [[ObjectA alloc] init];  // retainCount of `obj1` object = +1
   ObjectA * obj2 = [obj1 copy];             // retainCount of `obj2` object = +1

   // you have two instances of `ObjectA`, each with a retain count of +1
   // `obj1` points to one instance and `obj2` point to the other
}

-(void) fun4
{
   ObjectA * obj1 = [[ObjectA alloc] init];  // retainCount of `obj1` object = +1
   ObjectA * obj2 = [obj1 mutableCopy];      // retainCount of `obj2` object = +1

   // you have two instances of `ObjectA`, each with a retain count of +1
   // `obj1` points to one instance
   // `obj2` points to another instance, which is mutable copy of the `obj1` instance
}

@end

显然,在所有这些情况下,在MRR中,如果你在方法结束时没有对ObjectA实例做某事,你就会泄漏(因为你放弃了最后的已知)参考这些对象)。如果使用ARC,则执行必要的清理。

顺便说一下,将来你应该自己检查结果。例如,如果您将这些诊断语句添加到每个方法的末尾,您就会清楚地看到正在发生的事情:

NSLog(@"%s: [obj1 (%p) retainCount] = %d", __FUNCTION__, obj1, [obj1 retainCount]);
NSLog(@"%s: [obj2 (%p) retainCount] = %d", __FUNCTION__, obj2, [obj2 retainCount]);

显示变量指向的对象的地址,以及对象的当前retainCount。不用说,您不应该在生产代码中使用retainCount,但它仅用于诊断目的。

顺便说一下,虽然你试图理解内存管理是好的,但我建议你认真考虑使用automatic reference counting(ARC)。它使内存管理变得更加容易(没有retainreleaseretainCount)。如果您决定坚持使用手动保留和释放(MRR),那么请确保通过静态分析器运行代码(Xcode的“产品”菜单上的“分析”),因为它在识别问题时非常不错那可能是MRR代码。

答案 1 :(得分:1)

每当你写保留它只是一个简单的区别它将增加计数,每当你写副本时它将作出参考并且不增加计数例如让我们说: -

  NSObject *ret=[obj1 retain];
  It will increment the count by 1in      
  memory(count will become 2)

  NSObject *cop=[obj1 copy];
 It will not increment the count here count will    
  be 1only it just create the new reference in 
  memory. (count will remain same 1 only)