您创建的对象的所有权
Ownage of objects you create
我知道讨论过很多次,但是我在学习内存管理的时候有一点很迷茫
它表示,您拥有对象的所有权,您可以使用 alloc/copy/new/mutableCopy 或类似方法(如 allocWithSomething)创建对象。
但是,当你在 ARC 中创建像 NSArray *arr = [NSArray array];
这样的对象时,它相当于写 NSArray *arr = [[NSArray array]autorelease];
但是,我看到很多次这样的说法 - 您拥有您创建的每个对象。但在上面的例子中,我们实际上并没有拥有对象,我们只是将它添加到 autorelease pool
。因此,我们不必 retain/release 它,一旦它离开函数范围,它就会消失(正如 Apple 所说,在 "event" 之后)。
你能为我澄清一下那个时刻吗,我们真的拥有我们创建的每个对象,还是只拥有使用 alloc/copy/mutableCopy/new 创建的对象,因此将它们的保留计数增加 +1?
这是 objective-C 中所有权术语的问题。最简单的规则是,如果对象必须在我们使用完后释放,则我们拥有该对象。因此,首先所有者可以是 class,可以是方法或函数,甚至是块,还有更多。同一个对象可能有多个所有者。
释放可以通过release
方法或autorelease
方法调用。我们将它添加到自动释放池以延迟其释放,直到池被耗尽,这在大多数情况下是在运行循环结束时。您发布的代码对于 [[NSArray array]autorelease];
是错误的,因为这会导致您的应用程序因过度发布而崩溃。正确的版本是 [[NSArray new] autorelease];
,这或多或少是静态方法 array
returns.
因此,如果我们暂时排除 autorelease
,我们有 3 个元素:retain
将取得对象的所有权并增加保留计数,同时迫使您在某个时候释放它; release
将放弃所有权,减少保留计数,如果保留计数降为零(调用者是最后一个所有者),则可能会释放对象;对象创建规则说,所有包含 create、alloc、new、copy... 的方法或函数都会给你所有权而不保留它们,你有责任在它们上显式调用 release。
创建对象时,它的保留计数为 1。这意味着我们调用 alloc
+init
或任何版本的每个对象的保留计数都为 1,并且需要被明确释放。 [NSArray array]
等所有其他静态方法只不过是 [[[NSArray alloc] init] autorelease]
的便利,需要保留这些方法才能接管所有权。
所以基本上如果你有一个 class 有一个数组指针 NSArray *_array
并且我们想要获得所有权我们必须写 _array = [someArray retain]
和 dealloc
方法我们必须写 [_array release]
。如果一个方法需要获取所有权,我们需要调用 [someArray retain]
并且当我们完成它时我们需要调用 [someArray release]
除非我们 return 对象本身我们需要调用 return [someArray autorelease]
。这些是一个非常简单的规则,但其他一些情况使其极难追踪。所以 ARC 所做的就是为您在代码中插入这些调用,您无需担心它们。这些相同的程序仍然存在,就像他们在 ARC 之前所做的那样。
因此,ARC 究竟如何插入这些调用并没有真正解释,并且与版本不同。但是,如果我们再次查看您发布的示例,但让我们对其进行扩展:
- (NSArray *)foo // ARC version
{
NSArray *arr = [NSArray array];
for(NSObject *object in arr) NSLog(@"%@", object.description);
arr = [arr arrayByAddingObject:@"added something"];
return arr;
}
- (NSArray *)foo // ARC most likely behind the scenes
{
NSArray *arr = [[NSArray array] retain]; // reatin to claim ownership
for(NSObject *object in arr) NSLog(@"%@", object.description);
[arr autorelease]; // need to release it as it will be lost in the next line
arr = [[arr arrayByAddingObject:@"added something"] retain]; // the arr pointer now points to a different object. Claim the ownership of it
return [arr autorelease]; // need to relinquish the ownership
}
- (NSArray *)foo // standart non ARC wersion
{
NSArray *arr = [[NSArray alloc] init]; // we have the ownership by default
for(NSObject *object in arr) NSLog(@"%@", object.description);
NSArray *newArray = [[arr arrayByAddingObject:@"added something"] retain]; // need to explicitly retain this one as it is on the autorelease pool
[arr release]; // We do not need it anymore
return [newArray autorelease]; // need to relinquish the ownership
}
这可能过于简单化了,但是当你调用[NSArray数组]时,你实际上并不是在请求内存space,NSArrayclass正在为你做这件事。 NSArray class 有一个可能看起来像的方法:
+ (NSArray *) array
{
return [[[NSArray alloc] init] autorelease];
}
所以它创建对象 "owns" 它,而不是你。
与其说是"owning",不如说是"responsible for"。如果您使用 alloc 和类似方法为对象请求内存,那么您有责任释放该内存。
您拥有您创建的每个对象 - 只要您希望拥有它。 "Owning" 表示您持有该对象的保留计数,并且您将释放该保留计数,或者将责任和所有权转移给其他人。
[[NSArray alloc] init...]
创建一个您当时拥有的对象,保留计数为 1。您可以将该对象传递给接管所有权的其他人。
[NSArray array]
创建并 returns 一个对象,但立即将其添加到自动释放池中。该对象返回时不属于任何人;自动释放池只是防止它被释放,直到自动释放池本身消失。任何愿意的人都可以获得该对象的所有权。当然,不止一位代码可以获得该对象的所有权。当每个人都释放所有权时,对象将消失,当自动释放池也消失时。
无论如何,ARC 会为您处理所有这些事情。
我知道讨论过很多次,但是我在学习内存管理的时候有一点很迷茫
它表示,您拥有对象的所有权,您可以使用 alloc/copy/new/mutableCopy 或类似方法(如 allocWithSomething)创建对象。
但是,当你在 ARC 中创建像 NSArray *arr = [NSArray array];
这样的对象时,它相当于写 NSArray *arr = [[NSArray array]autorelease];
但是,我看到很多次这样的说法 - 您拥有您创建的每个对象。但在上面的例子中,我们实际上并没有拥有对象,我们只是将它添加到 autorelease pool
。因此,我们不必 retain/release 它,一旦它离开函数范围,它就会消失(正如 Apple 所说,在 "event" 之后)。
你能为我澄清一下那个时刻吗,我们真的拥有我们创建的每个对象,还是只拥有使用 alloc/copy/mutableCopy/new 创建的对象,因此将它们的保留计数增加 +1?
这是 objective-C 中所有权术语的问题。最简单的规则是,如果对象必须在我们使用完后释放,则我们拥有该对象。因此,首先所有者可以是 class,可以是方法或函数,甚至是块,还有更多。同一个对象可能有多个所有者。
释放可以通过release
方法或autorelease
方法调用。我们将它添加到自动释放池以延迟其释放,直到池被耗尽,这在大多数情况下是在运行循环结束时。您发布的代码对于 [[NSArray array]autorelease];
是错误的,因为这会导致您的应用程序因过度发布而崩溃。正确的版本是 [[NSArray new] autorelease];
,这或多或少是静态方法 array
returns.
因此,如果我们暂时排除 autorelease
,我们有 3 个元素:retain
将取得对象的所有权并增加保留计数,同时迫使您在某个时候释放它; release
将放弃所有权,减少保留计数,如果保留计数降为零(调用者是最后一个所有者),则可能会释放对象;对象创建规则说,所有包含 create、alloc、new、copy... 的方法或函数都会给你所有权而不保留它们,你有责任在它们上显式调用 release。
创建对象时,它的保留计数为 1。这意味着我们调用 alloc
+init
或任何版本的每个对象的保留计数都为 1,并且需要被明确释放。 [NSArray array]
等所有其他静态方法只不过是 [[[NSArray alloc] init] autorelease]
的便利,需要保留这些方法才能接管所有权。
所以基本上如果你有一个 class 有一个数组指针 NSArray *_array
并且我们想要获得所有权我们必须写 _array = [someArray retain]
和 dealloc
方法我们必须写 [_array release]
。如果一个方法需要获取所有权,我们需要调用 [someArray retain]
并且当我们完成它时我们需要调用 [someArray release]
除非我们 return 对象本身我们需要调用 return [someArray autorelease]
。这些是一个非常简单的规则,但其他一些情况使其极难追踪。所以 ARC 所做的就是为您在代码中插入这些调用,您无需担心它们。这些相同的程序仍然存在,就像他们在 ARC 之前所做的那样。
因此,ARC 究竟如何插入这些调用并没有真正解释,并且与版本不同。但是,如果我们再次查看您发布的示例,但让我们对其进行扩展:
- (NSArray *)foo // ARC version
{
NSArray *arr = [NSArray array];
for(NSObject *object in arr) NSLog(@"%@", object.description);
arr = [arr arrayByAddingObject:@"added something"];
return arr;
}
- (NSArray *)foo // ARC most likely behind the scenes
{
NSArray *arr = [[NSArray array] retain]; // reatin to claim ownership
for(NSObject *object in arr) NSLog(@"%@", object.description);
[arr autorelease]; // need to release it as it will be lost in the next line
arr = [[arr arrayByAddingObject:@"added something"] retain]; // the arr pointer now points to a different object. Claim the ownership of it
return [arr autorelease]; // need to relinquish the ownership
}
- (NSArray *)foo // standart non ARC wersion
{
NSArray *arr = [[NSArray alloc] init]; // we have the ownership by default
for(NSObject *object in arr) NSLog(@"%@", object.description);
NSArray *newArray = [[arr arrayByAddingObject:@"added something"] retain]; // need to explicitly retain this one as it is on the autorelease pool
[arr release]; // We do not need it anymore
return [newArray autorelease]; // need to relinquish the ownership
}
这可能过于简单化了,但是当你调用[NSArray数组]时,你实际上并不是在请求内存space,NSArrayclass正在为你做这件事。 NSArray class 有一个可能看起来像的方法:
+ (NSArray *) array
{
return [[[NSArray alloc] init] autorelease];
}
所以它创建对象 "owns" 它,而不是你。
与其说是"owning",不如说是"responsible for"。如果您使用 alloc 和类似方法为对象请求内存,那么您有责任释放该内存。
您拥有您创建的每个对象 - 只要您希望拥有它。 "Owning" 表示您持有该对象的保留计数,并且您将释放该保留计数,或者将责任和所有权转移给其他人。
[[NSArray alloc] init...]
创建一个您当时拥有的对象,保留计数为 1。您可以将该对象传递给接管所有权的其他人。
[NSArray array]
创建并 returns 一个对象,但立即将其添加到自动释放池中。该对象返回时不属于任何人;自动释放池只是防止它被释放,直到自动释放池本身消失。任何愿意的人都可以获得该对象的所有权。当然,不止一位代码可以获得该对象的所有权。当每个人都释放所有权时,对象将消失,当自动释放池也消失时。
无论如何,ARC 会为您处理所有这些事情。