1

我有这样的代码:

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吗?
4

2 回答 2

3

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

它将减轻您遇到的许多潜在内存问题。

此外,我会坚持使用 Foundation 集合,例如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];
  }
}
于 2012-09-08T03:10:03.877 回答
3

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

如果您使用而不是使用. 这是因为遵循 Cocoa 内存管理规则的方法以一种很好的方式协同工作;但是 的 方法不是用retains 和releases 写的,所以不遵循Cocoa 手动引用计数规则。因此,除非您使用 ARC,否则您将不得不自己打破内存管理规则,以便从外部显式地对其进行内存管理。这太可怕了,会教给你错误的想法。vectorNSArrayvector

Cocoa 内存管理的伟大之处在于它完全是本地的。你只根据你在函数中做了什么来保留和释放,你永远不必担心其他函数做了什么。这就是使静态分析内存管理和实现 ARC 成为可能的原因。

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

这包括将东西添加到NSArray

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

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

另一个例子:

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

这做了一些异步的事情,那么我们怎样才能释放它呢?使用时不会失效吗?不,这一切都遵循相同的内存管理规则。您无需担心该方法的作用。如果它需要以某种方式保留对象(在这种情况下确实如此),它必须保留它(确实如此)并注意释放它等。

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

于 2012-09-09T08:56:41.307 回答