我有这样的代码:
vector<SoundObject*> sounds ;
- (void) loadSound:(NSString*) name
{
SoundObject* so = [[[SoundObject alloc] init] load:name] ;
if( so )
sounds.push_back( so ) ;
}
好的,所以我在这里做了几件事(我可能会非常注重内存泄漏)。
[so retain]
推入数组之前,我应该致电so
吗?load
可能会失败,如果失败,则会返回nil
。
load
失败,在从[self release]
返回之前是否必须致电load
? 答案 0 :(得分:3)
如果您正在编写新代码,则应使用自动引用计数(ARC)。
它将缓解您遇到的许多潜在的内存问题。
此外,我会坚持使用基础集合,例如NSArray或NSMutableArray,而不是看起来像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或任何其他类如何正确地进行内存管理。您甚至不需要知道myArray
或addObject:
的对象类型。该方法负责处理 - 如果需要将对象保持更长时间,它必须(作为内存管理规则的一部分)以某种方式保留它;如果它不需要保留它,它不需要做任何事情。关键是,这对你没关系。
另一个例子:
Foo *obj = [[Foo alloc] init];
[someObj performSelector:@selector(something:) withObject:obj afterDelay:5];
[obj release];
这是异步的,所以我们如何释放它呢?它被使用时不会无效吗?不,这一切都遵循相同的内存管理规则。您无需担心该方法的作用。如果它需要以某种方式保持对象(在这种情况下确实如此),它必须保留它(它确实存在)并负责释放它等等。
如果你试图强迫像vector
这样的东西,所有这些简单和美丽就会消失。在放入之前你必须保留东西,并在每次删除元素时释放东西。这很糟糕。你可以围绕向量写一个包装类,这样你就可以在该文件中拥有所有可怕的内存管理逻辑,而其他人可以将它用作普通的Objective-C类;但那就像NSMutableArray
。