内存管理(2) - property修饰符和object所有权

前言

property修饰符和object所有权有一些关联。


1、属性中的修饰符的内存管理实现

  • assign(默认)(ARC、MRC都有)

    用于CGFloat、NSInteger、基本数据类型(c类型)
    用于不保留变量的对象、即相当创建弱引用而避免循环引用的发生

- (void)setter:(tupe *)xxxx     //调用其setter方法时
{
    _xxxx = xxxx; //直接赋值
}

  • strong(默认)(仅ARC有)

    strong表示强引用关系,拥有对象的所有权(拥有对象的所有权即意味着要对其拥有的对象进行释放),引用计数器会加一

- (void) setter:(type *)XXXX     //调用其setter方法时
{
    [XXXX retain];      //新值引用计数加一保留
    [_xxxx release];    //旧值引用计数减一释放 
    _xxxx = XXXX;      
}

  • weak(仅ARC有)

    weak表示弱引用关系,不拥有对象的所有权,目标对象销毁之后,属性会设置为nil

- (void) setter:(type *)XXXX
{
    _xxxx = XXXX;   /* 相当直接赋值,引用计数器不回加1 */
}
//当[XXXX release] , _xxxx == nil,即原来的指针变量指向的对象释放后,指针变量 = nil

  • copy(ARC、MRC都有)

    copy引用计数加一,操作一个内存,注意在源对象可变(深拷贝)不可变(浅拷贝)时候的问题

- (void) setter:(type *)XXXX
{
    [XXXX retain];      //新值引用计数加一保留
    [_xxxx release];    //旧值引用计数减一释放 
    _xxxx = [XXXX copy];      //返回一个不可变的类型
}

  • retain(仅MRC有)

    retain为当前对象指向的对象 引用计数+1保证不被释放


2、ARC的几个对象所有权关键字__strong 、__weak、__autoreleasing、__unsafe_unretained

  • __strong(默认),只要有一个强指针指向对象,对象就不会释放

自己生成对象并持有

    id __strong obj = [[NSObject alloc] init];

等价于

    id obj = objc_msgSend(NSObject, @selector(alloc));  
    objc_msgSend(obj,@selector(init));          //
    objc_release(obj); 

自己不生成对象,但对象存在而持有

    id __strong obj = [NSMutableArray array];

等价于

    id obj = objc_msgSend(NSMutableArray, @selector(array));  
    objc_release(obj); 

  • __weak,不保持引用对象的存活,没有强引用指向它,那么弱引用置为nil

只能修饰对象类型,不能修饰基本类型

    Number* __weak num = [[Number alloc] init];

__weak修饰的指针变量指向的对象被释放时,指针变量会被设置为nil

    id __weak obj1 = obj;  

在编译器中实际上等价于:

    id obj1;            //定义一个id类型的指针变量
    obj1 = 0;             //将指针变量置为nil
    objc_storeWeak(&obj1, obj);      //让指针变量obj1 指向 obj
    objc_storeWeak(&obj1, 0);      //让指针变量obj1 指向 nil

__weak实现原理

objc_storeWeak()函数会把第二个参数的对象的地址作为key,并将第一个参数(__weak关键字修饰的指针的地址)作为值,注册到weak表中。如果第二个参数为0(说明对应的对象被释放了),则将weak表中将整个key-value键值对删除


  • __autoreleasing

使用__autoreleasing修饰的指针变量会会注册到autoreleasepool中,和在非ARC中[对象 autorelease]效果相同

    Number* __autoreleasing num = [[Number alloc] init];

访问附有__weak修饰符的指针变量时,该变量会被自动注册到autoreleasepool中

id __weak obj1 = obj0;  
NSLog("class=%@", [obj1 class]);  

//等价于以下代码  
id __weak obj1 = obj0;  
id __autoreleasing tmp = obj1;  
NSLog("class=%@", [tmp class]);  

_objc_autoreleasePoolPrint()函数

该函数属于私有函数,可以打印出注册到调用函数处所属的autoreleasepool中的对象。


  • __unsafe_unretained

__unsafe_unretained修饰符的变量也不能持有对象.

id __unsafe_unretained obj1 = obj;    
//即obj1不能持有对象

__unsafe_unretained修饰符的变量指向的对象被废弃了那么该指针变量的值不会被置为nil,依然还是以前的值.但它已经是野指针了,可能会导致问题


3、属性修饰符合对应的所有权修饰符

所有权的意思是,谁所有谁负责释放。

属性修饰符 对应的所有权修饰符 作用
strong (ARC) __strong 默认使用,对引用对象强引用
weak (ARC) __weak ARC才有的修饰符,对对象弱引用,对对象无持有权
copy (ARC、MRC) __strong(赋值的是复制的对象) 类似于strong,不过在赋值时进行copy而不是retain。一般用于保留某个不可变对象(如NSString),并防止它被意外改变
retain (MRC) __strong 基本等价于strong
assign (ARC、MRC) __unsafe_unretained 默认使用,setter方法直接赋值,不进行retain操作,一般用于处理基本数据类型
__unsafe_unretained (ARC) __unsafe_unretained 不安全的修饰符,修饰的变量不属于编译器的内存管理对象,基本等价于assign

猜你喜欢

转载自blog.csdn.net/qq_28446287/article/details/80157552