存储安全:确保变量先定义再使用

252 阅读3分钟

写在开头 iOS开发者 群173499350 给大家提供一个交流技术 也可以聊天打屁的平台

翻译自Swift官方Blog

  • 我们在用swift设计开发时的一个重点就是 如何提高编码模型的内存安全问题 本文讲解了一个内存安全的问题 : 如何确保变量有一个初始值才能使用。

  • swift版简介

变量什么时候是安全的 ? 开发者认为无论任何时候访问一个变量时 都有一个值 而不是nil 像其他编程语言 比如C 要求程序员对内存模型的编程技术非常严格 但是这是有风险的 人总会犯错C++OC用了其他方式改善这种可能造成错误的地方 如OC [nil message]会被忽视 有的语言要求更严格 不赋值 就无法编译 目前解决这种办法采用的技术是让编译器执行数据流分析 如果变量不初始化无法编译通过 像java C# 都采用这种技术 Definitive Initialization

                  注意Swift不仅仅使用这一项技术
  • 初始化一个局部变量 类型推断允许你这样写

    var myInstance : MyClass  // 定义一个非可选的局部变量
    
    if x > 42 {
    myInstance = MyClass(intValue: 13)
    } else {
      myInstance = MyClass(floatValue: 92.3)
      }
    
    // myInstance已经初始化 所以在下面可以使用
         myInstance.printIt()
    

这里很简单的可以确定变量已经初始化 可以保证不会访问那些未初始化的内存 避免Crash 但是有时候流程可能更加复杂

    var myInstance : MyClass

    if x > 10 {
    myInstance = MyClass(intValue: 13)
   }
    // ...其他操作
   if x > 42 {
   myInstance.printIt()
   }

这时编译器可能告诉你 “Variable myInstance used before initialized” on the call to printIt()其实就是说变量未初始化 编译器不可能做所有预测 或者类型推断 这就要求我们不要写这么复杂的逻辑 去初始化一个变量

在普通数据类型如int 初始化时可以直接这样 var index = 0 但是其他情况可能就要用到init()

  • 其他技术补充

鉴于C语言的兼容性 有时候我们需要使用一些C不安全的API 如UnsafePointer 这样的代码会造成程序运行时Crash 这就要求程序员永远不犯错

  • 隐式初始化

有些编程语言会有一些默认值 比如声明一个变量 int a未给这个变量赋值的情况下 我们就给一个默认值 r如0 但是Swift 没有采用这种考虑 原因如下

  1. 如果有些Protocol没有要求实现init()方法 这样一个变量就可能引用一个未初始化的对象 遗留在Cocoa编程中 这种情况太常见了

  2. 就算不给变量默认值 自己写一个也并不麻烦 而且会提前发现很多错误 使代码更容易维护

注意 只有可选类型或者隐式可选默认值才是nil

 所以Swift采用了 访问一个变量前必须初始化

参考