• [Objective-C语言教程]内存管理(36)


    内存管理是任何编程语言中最重要的过程之一。它是在需要时分配对象的内存并在不再需要时取消分配的过程。

    管理对象内存是一个性能问题; 如果应用程序不释放不需要的对象,则应用程序会因内存占用增加并且性能受损。

    Objective-C内存管理技术大致可分为两类 -

    • “手动保留或释放”或MRR
    • “自动参考计数”或ARC

    1. “手动保留释放”或MRR

    在MRR中,通过跟踪自己的对象来明确管理内存。这是使用一个称为引用计数的模型实现的,FoundationNSObject与运行时环境一起提供。

    MRR和ARC之间的唯一区别是保留和释放,前者是手动处理,而后者则自动处理。

    下图表示内存管理在Objective-C中的工作方式示例。

    A类对象的内存生命周期如上图所示。 如您所见,保留计数显示在对象下方,当对象的保留计数变为0时,对象将被完全释放,并且其内存将被释放以供其他对象使用。

    首先使用NSObject中提供的alloc/init方法创建A类对象。 现在,保留计数变为1
    现在,B类保留了A类的对象,A类对象的保留计数变为2

    然后,C类拷贝该对象的副本。它被创建为A类的另一个实例,具有相同的实例变量值。 这里,保留计数是1而不是原始对象的保留计数。如图中的虚线表示。

    使用release方法由C类释放复制的对象,并且保留计数变为0,因此对象被销毁。

    对于初始的A类对象,保留计数为2,所以必须释放两次才能销毁它。 这是通过A类和B类的释放语句完成的,它们将保留计数分别减少到10。 最后,对象就被销毁了。

    2. MRR基本规则

    • 拥有创建的任何对象:使用名称以“alloc”,“new”,“copy”或“mutableCopy”开头的方法创建对象

    • 使用retain获取对象的所有权:通常保证接收到的对象在接收到的方法中保持有效,并且该方法也可以安全地将对象返回给它的调用者。在两种情况下使用retain -

      • 在访问器方法或init方法的实现中,获取想要存储为对象属性值的对象的所有权。
      • 防止对象因某些其他操作的副作用而失效。
    • 当不再需要它时,必须放弃对拥有的对象的所有权:通过向对象发送释放消息或自动释放消息来放弃对象的所有权。 因此,在Cocoa术语中,放弃对象的所有权通常被称为“释放”对象。

    • 不得放弃不拥有的对象的所有权。

    示例代码

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface SampleClass:NSObject
     4 - (void)sampleMethod;
     5 @end
     6 
     7 @implementation SampleClass
     8 - (void)sampleMethod {
     9    NSLog(@"Hello, World! 
    ");
    10 }
    11 
    12 - (void)dealloc  {
    13   NSLog(@"Object deallocated");
    14   [super dealloc];
    15 }
    16 
    17 @end
    18 
    19 int main() {
    20 
    21    /* 第一个Objective-C程序 */
    22    SampleClass *sampleClass = [[SampleClass alloc]init];
    23    [sampleClass sampleMethod];
    24 
    25    NSLog(@"Retain Count after initial allocation: %d", 
    26    [sampleClass retainCount]);
    27    [sampleClass retain];
    28 
    29    NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]);
    30    [sampleClass release];
    31    NSLog(@"Retain Count after release: %d", [sampleClass retainCount]);
    32    [sampleClass release];
    33    NSLog(@"SampleClass dealloc will be called before this");
    34 
    35    // 应该将对象设置为nil
    36    sampleClass = nil;
    37    return 0;
    38 }

    执行上面示例代码,得到以下结果 -

    1 2018-11-16 07:02:42.556 main[152785] Hello, World! 
    2 2018-11-16 07:02:42.558 main[152785] Retain Count after initial allocation: 1
    3 2018-11-16 07:02:42.558 main[152785] Retain Count after retain: 2
    4 2018-11-16 07:02:42.558 main[152785] Retain Count after release: 1
    5 2018-11-16 07:02:42.558 main[152785] Object deallocated
    6 2018-11-16 07:02:42.558 main[152785] SampleClass dealloc will be called before this

    3. “自动参考计数”或ARC

    在自动引用计数或ARC中,系统使用与MRR相同的引用计数系统,但它在编译时为我们插入适当的内存管理方法调用。 强烈建议将ARC用于新项目。 如果使用ARC,通常不需要理解本文档中描述的底层实现,尽管在某些情况下它可能会有所帮助。 有关ARC的更多信息,请参阅ARC发行说明

    如上所述,在ARC中,不需要添加releaseretain方法,因为编译器会对此进行处理。 实际上,Objective-C的基本过程仍然是相同的。 它在内部使用保留和释放操作,使开发人员更容易编码而无需担心这些操作,这将减少写入的代码量和内存泄漏的可能性。

    还有另一个原则叫做垃圾收集,它在Mac OS-X中与MRR一起使用,但由于它在OS-X Mountain Lion中的弃用,它还没有与MRR一起讨论过。 此外,iOS对象从未拥有垃圾收集功能。 使用ARC,OS-X中也没有使用垃圾收集。

    这是一个简单的ARC示例。 请注意,这不适用于在线编译器,因为它不支持ARC。

     1 #import <Foundation/Foundation.h>
     2 
     3 @interface SampleClass:NSObject
     4 - (void)sampleMethod;
     5 @end
     6 
     7 @implementation SampleClass
     8 - (void)sampleMethod {
     9    NSLog(@"Hello, World! 
    ");
    10 }
    11 
    12 - (void)dealloc  {
    13   NSLog(@"Object deallocated");
    14 }
    15 
    16 @end
    17 
    18 int main() {
    19    /* my first program in Objective-C */
    20    @autoreleasepool {
    21       SampleClass *sampleClass = [[SampleClass alloc]init];
    22       [sampleClass sampleMethod];
    23       sampleClass = nil;
    24    }
    25    return 0;
    26 }

    执行上面示例代码,得到以下结果 -

    1 2018-10-28 08:45:17.210 demo[8385] Hello, World!
    2 2018-10-28 08:45:17.211 demo[8385] Object deallocated
  • 相关阅读:
    SecureCRT 连接 虚拟机Linux 命令
    如何使用secureCRT连接vmware中的虚拟主机?
    SecureCRT8.1+SecureCRT_keygen完成注册
    常用python机器学习库总结
    Torch7在Ubuntu下的安装与配置
    朴素贝叶斯算法 & 应用实例
    编写MR代码中,JAVA注意事项
    march.
    Docker CentOS 7.2镜像systemd问题解决办法
    Docker 基础命令 简要入门
  • 原文地址:https://www.cnblogs.com/strengthen/p/10572767.html
Copyright © 2020-2023  润新知