如果我在结构中分离对象,会在内存方面发生什么

时间:2015-02-20 17:24:38

标签: ios iphone cocoa ipad cocoa-touch

假设这种情况。我有一个具有这些属性的Person类:

  • parent(weak) - 保存对person父对象的引用
  • 儿童(强) - 是该人的一系列儿童
  • director - 布尔持有一个标记,用于标记此人是否为层次结构中的导演

然后我有一系列员工。只有该公司所有分支机构的首席执行官才会加入该阵列。员工作为孩子被添加到他们各自的不同层次的老板。

看起来像这样(在这个例子中,你只看到一个CEO加入了数组):

      JACK (CEO)
          |
   ---------------       
   |              |
  BOB            TOM  
                  |
                  |
              ---------
             |         |
            LAURA    CARRY 
                       |  
                      TONY

看看正确的分支。 Tony是Carry的孩子,他是Tom的孩子,是Jack的孩子。每个人都强烈提及其孩子,并且弱势地提及其父母。

如果我从杰克的儿童阵列中移除汤姆,会在记忆方面发生什么?整个分支Tom,Laura,Carry和Tony从记忆中释放出来,或者我必须打破每个元素之间的所有联系,例如,Carry和Tony之间,Tom和它的孩子之间等等。

2 个答案:

答案 0 :(得分:2)

整个分支被释放;你不需要再做任何工作了。

在实践中,正在发生的事情是,当Tom从Jack的所有权中解脱出来时,它将释放它所持有的任何强引用,这在参考树上递归发生。

答案 1 :(得分:1)

一个小实验

#import <Foundation/Foundation.h>


@interface Person : NSObject
@property (copy, nonatomic) NSString * name;
@property (strong , nonatomic) NSMutableArray *children;
@property (weak, nonatomic) Person *parent;
@end

@implementation Person

- (instancetype)initWithName:(NSString *)name
{
    self = [super init];
    if (self) {
        _name = name;
        _children = [@[] mutableCopy];
    }
    return self;
}

-(void)dealloc
{
    NSLog(@"dealloc %@", self.name);
}
@end


int main(int argc, const char * argv[]) {

    //family's scope is the main function. it will exist till the app stops.
    NSMutableArray *family = [@[] mutableCopy];

    @autoreleasepool {

        Person *p0 = [[Person alloc] initWithName:@"father"];
        Person *c1 = [[Person alloc] initWithName:@"child 1"];
        Person *c2 = [[Person alloc] initWithName:@"child 2"];
        [p0.children addObject:c1];
        [p0.children addObject:c2];

        [family addObject:p0];
        [family removeObjectAtIndex:0];
        // p0, c1, c2 are defined in this scope. but family is defined 
        // in the scope of main()
    }
    while (YES) { // needed to give NSLog enough time
    }
    return 0;
}

如果您运行此代码,它将产生

2015-02-20 18:50:40.618 persons[66846:956945] dealloc father
2015-02-20 18:50:40.619 persons[66846:956945] dealloc child 1
2015-02-20 18:50:40.619 persons[66846:956945] dealloc child 2

如果您删除[family removeObjectAtIndex:0];,则不会打印任何内容。

规则是:只要一个对象被另一个对象强烈引用,它就不会被释放。如果不存在更强的引用,则将其解除分配。定义它的范围有一个强引用(这就是为什么我将代码包装在自动释放池中,否则主函数将是范围)。