在创建对象时,我应该[保留]和[释放]然后将其添加到向量中吗?

时间:2012-09-08 03:02:47

标签: cocoa memory-management memory-leaks objective-c++

我有这样的代码:

vector<SoundObject*> sounds ;

- (void) loadSound:(NSString*) name
  {
    SoundObject* so = [[[SoundObject alloc] init] load:name] ;
    if( so )
      sounds.push_back( so ) ;
  }

好的,所以我在这里做了几件事(我可能会非常注重内存泄漏)。

  1. 在将[so retain]推入数组之前,我应该致电so吗?
  2. load可能会失败,如果失败,则会返回nil
    • 如果load失败,在从[self release]返回之前是否必须致电load

2 个答案:

答案 0 :(得分:3)

如果您正在编写新代码,则应使用自动引用计数(ARC)。

它将缓解您遇到的许多潜在的内存问题。

此外,我会坚持使用基础集合,例如NSArrayNSMutableArray,而不是看起来像C ++向量。

NSMutableArray *_myMutableArray = [[NSMutableArray alloc] init];

- (void)loadSound:(NSString *)name
{
  SoundObject *so = [[SoundObject alloc] init];

  if( nil != so )
  {
    [so load:name];

    [_myMutableArray addObject:so];
  }
}

答案 1 :(得分:3)

  

但这个问题的目的是了解Objective-C   引用计数

如果您使用vector而不是使用NSArray,您将了解 less 的Cocoa内存管理。这是因为遵循Cocoa内存管理规则的方法以一种很好的方式协同工作;但vector的方法不是用保留和发布编写的,因此不要遵循Cocoa手动引用计数规则。因此,除非您使用ARC,否则您将不得不自行打破内存管理规则,以便从外部对内存进行明确的内存管理。这很糟糕,会教你错误的想法。

Cocoa内存管理的好处在于它完全是本地的。您仅根据在函数中执行的操作保留和释放,并且从不必须担心其他函数的作用。这就是静态分析内存管理和实现ARC的原因。

我的意思是什么? Cocoa内存管理的基本规则是,当调用函数时,函数的对象参数保证有效(即不释放),并且不保证它在任何时间之后有效。而已。所以当你将一个参数传递给另一个函数时,只要该对象在你传递它时是有效的,那就是你需要担心的。您永远不需要“保留其他函数的对象”,因为其他函数无论如何都不能假定该对象在任何时候都有效。

这包括向NSArray添加内容:

Foo *obj = [[Foo alloc] init];
[myArray addObject:obj];
[obj release];

由于您在添加后不再需要obj,因此您可以自由发布它。你不需要担心别的什么。现在,正如其他人所说,这是有效的,因为数组保留了它的元素。 但你不需要知道。 NSArray方法遵循与所有其他对象方法相同的规则。您不需要知道NSArray或任何其他类如何正确地进行内存管理。您甚至不需要知道myArrayaddObject:的对象类型。该方法负责处理 - 如果需要将对象保持更长时间,它必须(作为内存管理规则的一部分)以某种方式保留它;如果它不需要保留它,它不需要做任何事情。关键是,这对你没关系。

另一个例子:

Foo *obj = [[Foo alloc] init];
[someObj performSelector:@selector(something:) withObject:obj afterDelay:5];
[obj release];

这是异步的,所以我们如何释放它呢?它被使用时不会无效吗?不,这一切都遵循相同的内存管理规则。您无需担心该方法的作用。如果它需要以某种方式保持对象(在这种情况下确实如此),它必须保留它(它确实存在)并负责释放它等等。

如果你试图强迫像vector这样的东西,所有这些简单和美丽就会消失。在放入之前你必须保留东西,并在每次删除元素时释放东西。这很糟糕。你可以围绕向量写一个包装类,这样你就可以在该文件中拥有所有可怕的内存管理逻辑,而其他人可以将它用作普通的Objective-C类;但那就像NSMutableArray