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

Nir*_*iya -3 cocoa objective-c ios

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

@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
Run Code Online (Sandbox Code Playgroud)

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

Rob*_*Rob 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
Run Code Online (Sandbox Code Playgroud)

显然,在所有这些情况下,在MRR中,如果ObjectA在方法结束时没有对实例执行某些操作,则会泄漏(因为您放弃了对这些对象的最后一次已知引用).如果使用ARC,则执行必要的清理.

顺便说一下,将来你应该自己检查结果.例如,如果您将这些诊断语句添加到每个方法的末尾,您将清楚地看到发生了什么:

NSLog(@"%s: [obj1 (%p) retainCount] = %d", __FUNCTION__, obj1, [obj1 retainCount]);
NSLog(@"%s: [obj2 (%p) retainCount] = %d", __FUNCTION__, obj2, [obj2 retainCount]);
Run Code Online (Sandbox Code Playgroud)

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

顺便说一下,虽然你试图理解内存管理是好的,但我建议你认真考虑使用自动引用计数(ARC).它使内存管理更容易(不retain,releaseretainCount).如果您决定坚持使用手动保留和释放(MRR),那么请确保通过静态分析器(Xcode的"产品"菜单上的"分析")运行代码,因为它在识别问题时非常不错瘟疫MRR代码.