博客
关于我
__unsafe_unretained ownership qualifier
阅读量:611 次
发布时间:2019-03-11

本文共 2306 字,大约阅读时间需要 7 分钟。

Objective-C 内存管理中的 _unsafe_unretained、_weak 和 _autoreleasing

在 Objective-C 开发中,_unsafe_unretained、_weak 和 _autoreleasing 这三个级别修饰词在内存管理中起着关键作用。每个修饰词适用于不同的场景,帮助开发者更好地管理对象的生命周期。本文将深入探讨这三个修饰词的使用方法及其最佳实践。


1. _unsafe_unretained 修饰

_unsafe_unretained 是一个弱引用级别修饰词,它意味着编译器不会管理对应的对象。与强引用(_strong)和弱引用(_weak)不同,_unsafe_unretained 不会自动保留对象,它完全依赖程序员手动管理。这种修饰通常用于以下场景:

  • 用于需要手动释放的对象:在非 ARC( Automatic Reference Counting, 自动引用计数)环境下,确实需要手动释放对象的场合。

  • 避免循环引用:在 ARC 中,使用 _unsafe_unretained 可能会导致循环引用,但开发者需要手动打破循环。

以代码为例:

id __unsafe_unretained obj1 = nil;{    id __strong obj0 = [[NSObject alloc] init];    obj1 = obj0;    NSLog(@"A: %@", obj1);}NSLog(@"B: %@", obj1);// 结果// A: ...// B: (空值或指向 hectares—悬挂指针)

在该代码中,obj1 使用了 _unsafe_unretained 修饰,因为它没有使用 allocnewcopy 等 способ持有对象的方法。因此,obj1obj0 离开作用域后会成为悬挂指针,导致内存泄漏或无效访问。


2. _weak 修饰

_weak 是一种弱引用,它的一个主要优势是不会阻止对象被释放。如果你拥有一个强引用并将其赋值给一个弱引用变量,强引用被释放后弱引用变量会变成 nil。这种设计目的是预防循环引用,并确保所有不再需要的对象被自动释放。

代码示例:

id __weak obj1 = obj0; // 假设 obj0 是一个强引用NSLog(@"obj1 类型:%@", [obj1 class]);

这里的 obj1 是一个弱引用,obj0 是一个强引用。如果在某个时候 obj1 成为悬挂指针,程序会自动将其设置为 nil,避免无效访问。


3. _autoreleasing 修饰

在 ARC 环境下,_autoreleasing 是一种自动释放对象的方式。它通过将对象注册到 NSAutoreleasePool 中,确保对象在不再被使用时被安全释放。

代码示例:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];id obj = [[NSObject alloc] init];[obj autorelease];[pool drain];

等价代码:

@autoreleasepool {    id __autoreleasing obj = [[NSObject alloc] init];}

@autoreleasepool 是一种更简洁的方式来使用 NSAutoreleasePool,它自动管理对象的释放,用户无需手动调用 autoreleasedrain 方法。


_weak 和 _autoreleasing 的关系

  • Weak 与释放池的关系
    弱引用变量总是会注册在释放池中。这意味着即使对象被强引用的某个弱引用变量持有,释放池仍然会管理它。代码如下:
  • id __weak obj1 = obj0;NSLog(@"obj1 类型:%@", [obj1 class]);id __autoreleasing tmp = obj1; // tmp 是 obj1 的强引用NSLog(@"tmp 类型:%@", [tmp class]);

    obj1 是 weak,会被释放池管理;tmp 是 autoreleasing,用于临时引用。

    1. 为什么要使用 weak?

      弱引用是为了解决循环引用的问题。如果一个对象 A 强引用了对象 B,对象 B 弱引用了对象 A,这种关系会导致内存泄漏。如果不用 weak,程序将无法正常释放对象 A 或 B。

    2. 如何优化内存管理?

      在 ARC 中,默认情况下指针是 id _autoreleasing *obj。如果你需要弱引用,可以将其改写为 id _weak *obj。例如:

    3. NSObject **obj = &[_NSObject new]; // 等价于 `id _autoreleasing *obj = [_NSObject new];`id __weak *obj = &[_NSObject new]; // 弱引用版本

      总结

      在 Objective-C 中选择正确的内存管理修饰词对于代码的安全性和可维护性至关重要。_unsafe_unretained 适用于手动管理对象;_weak 用于防止循环引用;而 _autoreleasing 在 ARC 中自动管理对象释放。通过合理地选择并使用这些修饰词,开发者可以更高效地管理内存,减少内存泄漏和悬挂指针的风险。

      如果你有更多关于内存管理的疑问,可以参考官方资料或权威开发指南,深入理解 ARC 的机制。

    转载地址:http://aettz.baihongyu.com/

    你可能感兴趣的文章
    Myeclipse常用快捷键
    查看>>
    MyEclipse更改项目名web发布名字不改问题
    查看>>
    MyEclipse用(JDBC)连接SQL出现的问题~
    查看>>
    mt-datetime-picker type="date" 时间格式 bug
    查看>>
    myeclipse的新建severlet不见解决方法
    查看>>
    MyEclipse设置当前行背景颜色、选中单词前景色、背景色
    查看>>
    Mtab书签导航程序 LinkStore/getIcon SQL注入漏洞复现
    查看>>
    myeclipse配置springmvc教程
    查看>>
    MyEclipse配置SVN
    查看>>
    MTCNN 人脸检测
    查看>>
    MyEcplise中SpringBoot怎样定制启动banner?
    查看>>
    MyPython
    查看>>
    MTD技术介绍
    查看>>
    MySQL
    查看>>
    MySQL
    查看>>
    mysql
    查看>>
    MTK Android 如何获取系统权限
    查看>>
    MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
    查看>>
    MySQL - ERROR 1406
    查看>>
    mysql - 视图
    查看>>