为什么Objective-C ARC解除分配取决于是否在功能中创建了对象? [英] Why is Objective-C ARC deallocation dependent on whether an object was created in function?

查看:57
本文介绍了为什么Objective-C ARC解除分配取决于是否在功能中创建了对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习有关ARC内存管理的知识,并且遇到了对我来说毫无意义的事情.

I'm learning about ARC memory management and ran across something that doesn't make sense to me.

在下面的示例代码中,如我期望的那样,当将其指针分配给nil时,在main()中本地分配的对象将被释放.

In the example code below, an object that is allocated locally in main() gets deallocated when its pointer is assigned to nil, as I would expect.

但是,如果在另一个函数中分配了相同类型的对象,并且在main()中定义了指向该对象的指针,并且将该指针设置为nil,则直到主函数退出,该对象才会被释放.对我来说这很神秘.

But if the same type of object is allocated in another function, and a pointer to it is defined in main(), and that pointer is set to nil, the object does not get deallocated until main function exits. That is mysterious to me.

在下面的代码中,创建了GRMemoryChecker类的两个实例.在一种情况下,它直接在main()中分配,而在另一种情况下,main()调用itemMakerFunc()进行分配.当运行main()时,日志输出显示在函数中分配的实例的指针设置为nil时未释放—在函数退出时将被释放.

In the code below, two instances of class GRMemoryChecker are created. In one case, it's allocated directly in main(), and in the other, main() calls itemMakerFunc() to do the allocation. When you run main(), the log output shows that the instance allocated in the function is not deallocated when its pointer is set to nil -- it's deallocated when the function exits.

我认为这意味着在指针设置为nil之前,由itemMakerFunc()创建的实例具有2个所有者,而在本地创建的实例只有1个.

I assume that means that the itemMakerFunc()-created instance has 2 owners before the pointer is set to nil, whereas the locally-created instance has only 1.

但是为什么呢?指针设置为nil时,还有哪些其他所有者存在?或者,如果仍然没有其他所有者存在,为什么柜台不存在时柜台不递减?

But why? What other owner is still in existence at the time the pointer is set to nil? Or if no other owner still exists, why wasn't the counter decremented when it went out of existence?

GRMemoryChecker.h:

#import <Foundation/Foundation.h>

@interface GRMemoryChecker : NSObject
{
    NSString *name;
}
- (id)initWithName:(NSString *)str;

- (void)setName:(NSString *)str;

- (void) dealloc;
@end

GRMemoryChecker.m:

#import "GRMemoryChecker.h"

@implementation GRMemoryChecker

- (id)initWithName:(NSString *)str
{
    self = [super init];
    if (self)
    {
        [self setName:str];
    }
    return self;
}

- (void)setName:(NSString *)str
{
    name = str;
}

- (NSString *)description
{
    return name;
}

- (void) dealloc;
{
    NSLog(@"Destroyed: %@", self);
}
@end

main.m:

#import <Foundation/Foundation.h>
#import "GRMemoryChecker.h"

GRMemoryChecker *itemMakerFunc()
{
    return [[GRMemoryChecker alloc] initWithName:@"func-based checker" ];
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        GRMemoryChecker *checkerLocallyCreated = [[GRMemoryChecker alloc] initWithName:@"locally-created checker"];
        GRMemoryChecker *checkerFuncBased = itemMakerFunc();

        NSLog(@"Before setting func-based checker pointer to nil");
        checkerFuncBased = nil;
        NSLog(@"After setting func-based checker pointer to nil");

        NSLog(@"Before setting locally-created checker pointer to nil");
        checkerLocallyCreated = nil;
        NSLog(@"After setting locally-created checker pointer to nil");
    }
    return 0;
}

控制台输出:

Before setting func-based checker pointer to nil
After setting func-based checker pointer to nil
Before setting locally-created checker pointer to nil
Destroyed: locally-created checker
After setting locally-created checker pointer to nil
Destroyed: func-based checker

推荐答案

ARC强制执行与您手动保留和释放对象时应遵循的相同的内存管理语义.因此,让我们看一下如何在MRR下编写此代码,看看是否可以告诉我们任何内容:

ARC enforces the same memory management semantics you're supposed to follow when you manually retain and release your objects. So let's look at how we would write this under MRR and see if that tells us anything:

GRMemoryChecker *itemMakerFunc()
{
    return [[[GRMemoryChecker alloc] initWithName:@"func-based checker" ] autorelease];
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        GRMemoryChecker *checkerLocallyCreated = [[GRMemoryChecker alloc] initWithName:@"locally-created checker"];
        GRMemoryChecker *checkerFuncBased = itemMakerFunc();

        NSLog(@"Before setting func-based checker pointer to nil");
        checkerFuncBased = nil;
        NSLog(@"After setting func-based checker pointer to nil");

        NSLog(@"Before setting locally-created checker pointer to nil");
        [checkerLocallyCreated release];
        checkerLocallyCreated = nil;
        NSLog(@"After setting locally-created checker pointer to nil");
    }
    return 0;
}

因此,基本上,alloc返回的引用是拥有的引用,需要释放.当一个对象仅存在于一个函数中时,我们可以直接释放它,并且将立即释放该对象.但是,当我们从函数中返回它时,我们不能简单地释放它,因为它需要保留在return语句之后,因此它会自动释放.

So basically, the reference returned by alloc is an owning reference, which needs to be released. When an object only lives in one function, we can release it directly and it will be immediately deallocated. But when we're returning it from the function, we can't simply release it, because it needs to live past the return statement, so it gets autoreleased.

这篇关于为什么Objective-C ARC解除分配取决于是否在功能中创建了对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆