• Objective C 中的nil,Nil,NULL和NSNull理解


      kenyo网友的原创说法是:做IOS开发的估计都对Objective-C的内存管理机制很头疼,一不小心程序就会出内存泄露,我也不例外,前几天被指针的置nil与release给搞惨了,今和大家详细解说一下有关Objective-C中nil与release的区别与用法。

        首先说一下他们两的作用,nil就是把一个对象的指针置为空,只是切断了指针与内存中对象的联系,它对内存的释放没有什么作用;而release才是真正用于内存释放的,release后系统会将该块内存标记为可用(可重新分配)。所以nil并没有释放内存,只有release才是真正释放内存。

        二者使用顺序,如果没有release就直接nil,那么虽然不会出错(release一个空指针是合法的),但却等于自己制造了内存泄漏,因为nil之后release就已经不起作用了,我之前的教训就是一不小心把nil搁在了release之前,所以leak一直报内存泄露。

        相反,如果先release后设置nil,就不会出现这样的问题,但是有人就会问,release而没有设置nil,会怎样?其实程序可能也不会报错,但是要知道设置nil其实是为了防止指针错乱,因为一个对象在release之后,给它所分配的内存就已经被释放了,如果释放之后不把指针置空的话,系统再误用到到这个指针时,那么程序就会崩溃(此种情况特别容易出现在延时调用函数中),如果释放之后把它的指针置为空,则即便后面的程序用到该指针,也不会崩溃。所以Objective-C释放内存时必须先release然后nil。

      还有一点,在子龙山人的原创文章中有这样的话:可能有读者经常看到,在我的教程的dealloc函数里面有这样的代码:self.xxx = nil;看到这里,现在你们明白这样写有什么用了吧?它等价于[xxx release];  xxx = [nil retain];(---如果你的property(nonatomic,retian)xxx,那么就会这样,如果不是,就对号入座吧)。这就是说,在使用了@property运算符后的类变量会产生set和get方法,而set方法的具体写法是这样的:

     

    -(void) setNames:(NSArray*)names{
    NSLog(@"setNames");
    if (_name != name) {
    [_name release];
    _name = [name retain]; }
    }
    原来的变量和nil比较,不等于就自动释放了,然后再执行xxx=[nil retain];语句

     

    nil

    • nil 是 ObjC 对象的字面空值,对应 id 类型的对象,或者使用 @interface 声明的 ObjC 对象。
    • 例如:
      NSString *someString = nil;
      NSURL *someURL = nil;
      id someObject = nil;
       
      if (anotherObject == nil) // do something
    • 定义:
      // objc.h
      #ifndef nil
      # if __has_feature(cxx_nullptr)
      #   define nil nullptr
      # else
      #   define nil __DARWIN_NULL
      # endif
      #endif
       
      // __DARWIN_NULL in _types.h
       
      #define __DARWIN_NULL ((void *)0)

    Nil

    • Nil 是 ObjC 类类型的书面空值,对应 Class 类型对象。
    • 例如:
      Class someClass = Nil;
      Class anotherClass = [NSString class];
    • 定义声明和 nil 是差不多的,值相同:
      // objc.h
      #ifndef Nil
      # if __has_feature(cxx_nullptr)
      #   define Nil nullptr
      # else
      #   define Nil __DARWIN_NULL
      # endif
      #endif

    NULL

    • NULL 是任意的 C 指针空值。
    • 例如:
      int *pointerToInt = NULL;
      char *pointerToChar = NULL;
      struct TreeNode *rootNode = NULL;
    • 定义:
      // in stddef.h
       
      #define NULL ((void*)0)

    NSNull

    • NSNull 是一个代表空值的类,是一个 ObjC 对象。实际上它只有一个单例方法:+[NSNull null],一般用于表示集合中值为空的对象。
    • 例子说明:
      // 因为 nil 被用来用为集合结束的标志,所以 nil 不能存储在 Foundation 集合里。
      NSArray *array = [NSArray arrayWithObjects:@"one", @"two", nil];
       
      // 错误的使用
      NSMutableDictionary *dict = [NSMutableDictionary dictionary];
      [dict setObject:nil forKey:@"someKey"];
       
      // 正确的使用
      NSMutableDictionary *dict = [NSMutableDictionary dictionary];
      [dict setObject:[NSNull null] forKey:@"someKey"];
    • 定义:
      /*  NSNull.h
          Copyright (c) 1994-2012, Apple Inc. All rights reserved.
      */
       
      #import <Foundation/NSObject.h>
       
      @interface NSNull : NSObject <NSCopying, NSSecureCoding>
       
      + (NSNull *)null;
       
      @end

    NIL 或 NSNil

    ObjC 不存在这两个符号!

    小结

    虽然 nil, Nil, NULL 的值相同,理解它们之间的书面意义才重要,让代码更加明确,增加可读性。

    参考资料

    object c 中的BOOL值与bool值

    typedef signed char BOOL;  

    #define YES      (BOOL) 1

    #define NO       (BOOL) 0

    从上面的定义我们发现布尔变量的值为 YES/NO,或 1/0 。YES 或 1 代表真,NO 或 0 代表假。比如你定义了一个布尔变量并赋了值:

    BOOL enabled = NO;
    enabled = 0;

    判断BOOL值为YES:

    if(enabled == YES){

    }

    或者YES可以省略

    if(enabled){

    }

    判断BOOL值为NO:

    if(!enabled){

    }

    或者

    if(enabled != YES){

    }

  • 相关阅读:
    Win32汇编之其他指令
    Win32汇编过程与宏调用
    Win32汇编常用算数指令
    SQLi-LABS Page-1(Basic Challenges) Less1-Less4
    8 Best DDoS Attack Tools (Free DDoS Tool Of The Year 2019)
    4. 移动安全渗透测试-(Android逆向基础)
    3. 移动安全渗透测试-(Android基础漏洞)
    2. 移动安全渗透测试-(Android安全基础)
    1. 移动安全渗透测试-(环境搭建)
    Hacking/Penetrating tester bookmark collection
  • 原文地址:https://www.cnblogs.com/baozou/p/3304096.html
Copyright © 2020-2023  润新知