__strong、__weak、__unsafe_unretained和__autoreleasing修饰符

来源:互联网 发布:淘宝买东西无法付款 编辑:程序博客网 时间:2024/05/29 17:11

内存管理始终遵循的几点:

    1、自己生成的对象,自己所持有。

    2、非自己生成的对象,自己也能持有。

    3、不再需要自己持有的对象时释放。

    4、非自己持有的对象,无法释放。

由于id类型和对象类型的所有权修饰符默认是__strong,所以,不需要写上"__strong".

__strong 大家都知道会造成循环引用,导致内存泄露,所以,__strong自己是无法管理好内存的,还需要另外一个修饰符,"__weak"

带有__strong的变量,持有该对象,然而,__weak的变量,却没有持有该对象,有效的避免了循环引用,而且__weak还有另外一个优点就是,_weak不持有该对象,当他拥有的对象被释放的时候,那此时这个若引用也会自动失效,并且被置为nil的状态。


下面用一个例子来说明__strong和__weak的区别

想象我们的对象是条狗,狗想要跑掉(即被释放)。

__strong型指针就像是拴住了这条狗,只要你用绳牵住这条狗狗就不会被跑掉。如果有5个人牵着这条狗(5个strong型指针指向这同一个对象),除非5个牵着的绳都脱落,否则狗是不会跑掉的。

__weak 型指针就像是一个小孩指着狗喊叫:“看!一条狗在那”只要狗被栓在那里,小孩就能看到狗,(__weak指针)会一直指向它,只要狗的牵绳脱落,狗就会跑掉,不管有多少小孩在看着它。

只要最后一个strong型的指针都没有指向他,那么这个对象就会被释放,同时,所有的weak型的指针都将会被清除。


__unsafe_unretained是跟__weak类似的用法,但是__unsafe_unretained会更易造成野指针,

并且需要注意的是,尽管ARC式的内存管理是编译器的工作,但是附有_unsafe_unretained修饰符的变量不属于编译器的内存管理对象

可以看如下两个例子来区别:__unsafe_unretained和__weak

第一个例子:

    __strongNSString *yourString = [[NSStringalloc]initWithUTF8String:"your string"];

    __weak NSString *myString = yourString;
    yourString = nil;
    __unsafe_unretainedNSString *theirString = myString;

    //现在所有的指针都为nil


第二个例子:

    __strongNSString *yourString = [[NSStringalloc]initWithUTF8String:"string 1"];

   __weak  NSString *myString = yourString;

   __unsafe_unretainedNSString *theirString = myString;

    yourString =nil;

    //现在yourStringmyString的指针都为nil,theirString不为nil,但是是野指针。


由此可以看到__unsafe_unretained是不安全的,不建议使用__unsafe_unretained。


__autoreleasing使用:


c/c++objective-c内存管理中有一条是:谁分配谁释放。 __autoreleasing则可以使对像延迟释放。比如你想传一个未初始化地对像引用到一个方法当中,在此方法中实始化此对像,那么这种情况将是__autoreleasing表演的时候。看个示例:


- (void) generateErrorInVariable:(__autoreleasingNSError **)paramError

{

   NSArray *objects = [[NSArrayalloc]initWithObjects:@"A simple error",nil];

    NSArray *keys = [[NSArrayalloc]initWithObjects:NSLocalizedDescriptionKey,nil];

   NSDictionary *errorDictionary = [[NSDictionaryalloc]initWithObjects:objectsforKeys:keys];

    *paramError = [[NSErroralloc]initWithDomain:@"MyApp"code:1userInfo:errorDictionary];

}

-(void)test

{

   NSError *error =nil;

    [selfgenerateErrorInVariable:&error];

   NSLog(@"Error = %@", error);

}

//被编译器翻译后就变为:

-(void)test

{

   NSError *error =nil;

   NSError *__autoreleasing tmp = error;

    [selfgenerateErrorInVariable:&tmp];

    error = tmp;

   NSLog(@"Error = %@", error);

}


这样即便在函数内部申请的空间,在函数外部也可以使用,同样也适合谁分配谁释放的原则。

以上就是对__strong、__weak、__unsafe_unretained和__autoreleasing修饰符的理解


0 0
原创粉丝点击