Tag: 指针

Swift内存布局:大小,步幅,对齐

Swift结构实例的内存布局的基础知识。 Swift类型在内存中处理时要考虑三个属性:大小,步幅和对齐。 尺寸 让我们从两个简单的结构开始: struct Year { let year: Int } struct YearWithMonth { let year: Int let month: Int } 我的直觉告诉我, YearWithMonth的实例比YearWithMonth的实例更大(它占用更多的内存空间)。 但是我们是这里的科学家。 我们如何用硬数字验证直觉? 内存布局 我们可以使用MemoryLayout类型来检查一些有关类型在内存中的外观的属性。 要从结构的类型中查找结构的size ,请使用size属性以及通用参数: let size = MemoryLayout.size 如果您有该类型的实例,请使用size(ofValue:)静态函数: let instance = Year(year: 1984) let size = MemoryLayout.size(ofValue: instance) 在这两种情况下,大小均报告为8个字节。 毫不奇怪,我们的结构YearWithMonth的大小为16个字节。 回到尺寸 结构的大小似乎很直观-计算每个属性的大小之和。 对于这样的结构: struct Puppy { let age: Int […]

使用Swift(Pre Swift 3)通过引用调用与按值调用

如果您是刚开始编程的人,没有太多的经验或对指针,地址和所有内存内容的了解,那么您可能会困惑于按引用调用(发生在类中)和按值调用(发生在结构中)。 如果您已经知道函数调用是什么,那么希望这对您有所帮助,使您在头脑中的区别更加清晰。 下面是显示内存和值差异的基本图。 物理内存地址是保存数据的位置。 该值就是该地址中保存的值。 了解这种差异很重要。 调用带有参数(或多个参数)的函数时,它可以采用值(整数,双精度型等)或引用(对象的实例)。 我们将从引用调用函数开始: 通过引用调用函数 当您有一个对象的实例,并将其分配给一个变量时,该变量实际上将保存该实例的物理地址。 因此,当您将其作为参数左右传递给不同的函数时,仅传递其地址比将整个对象移动更为有效,因为仅保存地址信息的变量所占用的存储空间比对象本身少(4个字节) (32位系统)和8位元组(64位系统)。 当变量的物理地址在调用函数时作为参数传递给函数时,可以说该函数是通过引用来调用的。 发生了什么事? 由于仅传递变量的地址,因此对该地址中的变量进行任何更改,该更改与调用函数时使用的变量相同! 因此,对变量进行的任何更改都会更改变量本身! 下面是一段代码和变量以及相关变量的地址的打印输出: 如您所见,当我们通过引用调用函数callMeByReference时,传递someNumber的地址,并在该函数内部更改该地址中的值时,它将更改someNumber的值,因为它是该地址中的变量! 在调用函数后打印出someNumber的值时,其值已更改! (即使函数不返回任何值) 通过值调用函数 但是,当您通过值调用函数时,会将参数复制(克隆)到内存的其他地址中。 即使给参数提供了与调用函数时使用的变量相同的名称,它也将是不同的变量(具有局部作用域,这意味着它仅在执行时才存在于函数体内) 为了证明我们的观点,请参见下面的代码和输出示例*: 所以,我们开始! 在将变量传递给函数callMeByReference及其地址0x0000000112097750之前,变量anotherNumber的值为3。 当函数具有参数anothermethod时,其值也为3,但其地址不同! 因为它与另一个Number不同,所以它只是一个克隆(代理人-布鲁斯威利斯的粉丝!!!)! 因此,即使我们更改参数anotherNumber的值,也不会更改函数外部的变量anotherNumber的值。 调用函数后,我们将输出anotherNumber变量的值和地址,但它们都没有改变,这证明了我们的观点! 我希望这可以帮助别人! *请不要很快就弃用“ var”参数。它们必须是一个常量(“ let”)。