-3

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

@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

我咨询了这个问题,但我仍然不清楚上述每个之间的区别。有人可以解释每个人的作用,以及为什么它们不同吗?

4

2 回答 2

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在生产代码中使用它,但它仅用于诊断目的。

顺便说一句,虽然您尝试了解内存管理很好,但我建议您认真考虑使用自动引用计数(ARC)。它使内存管理更容易(不retainreleaseretainCount)。如果您决定坚持手动保留和释放 (MRR),请确保您通过静态分析器运行代码(Xcode 的“产品”菜单上的“分析”),因为它在识别问题方面相当不错那个瘟疫MRR代码。

于 2013-10-14T14:28:12.043 回答
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)
于 2013-10-14T14:09:43.480 回答