空Swift字符串内存分配布局(堆栈/堆分配)

时间:2018-12-20 08:12:53

标签: swift string memory-management

迅速,字符串是结构类型,因此值将存储在堆栈内存中,而不是堆中。

假设我们声明一个字符串:

let a = ""
let b = "o"

这是一个空字符串,但是分配了一些内存。我需要知道给定一个空字符串和一个带有1的字符串的内存有什么区别。


如果我们说:-

var str:String?
var str: String = ""

我需要看到的是,通过绘图在内存布局上的差异。 (堆栈/堆)。

我试图在Google上找到它,但是没有地方找不到它的内存布局。

3 个答案:

答案 0 :(得分:9)

String非常复杂的野兽。它具有许多不同的基本表示形式,包括:

  • 字符串文字,以常量形式存储在二进制文件中

  • 小的字符串,可以在堆栈中内联最多存储15个UTF-8代码单元(至少在x86上)

  • “本地”字符串(即尚未桥接到Objective-C的字符串),这些字符串存储在尾部分配的堆缓冲区中

  • Obj-C中的“外来”字符串,可以用标记的指针或分配给堆的NSString对象来表示

  • “共享”字符串,可以将Swift字符串文字表示为分配给堆的Obj-C对象

如果您想深入了解具体细节,可以从StringObject.swift开始,其中有很多注释说明了一些布局细节。

要回答有关示例的问题:


let a = ""

一个空字符串有a canonical small string representation,它以内联方式存储在堆栈中。


let b = "o"

字符串文字以常量形式存储在二进制文件中。因此,不需要分配堆-仅需要指向二进制文件中字符串地址的指针。

但是,即使这不是常量字符串,例如,它也是由以下人员创建的:

let o = "O".lowercased()

然后它仍然可以表示为一个小的字符串,该字符串以内联方式存储在堆栈中。


var str: String?

String具有an extra inhabitant(至少在x86上),这意味着String?可以与String共享相同的布局。值nil由一种额外的居民位模式表示。

但是,即使String没有多余的居民,也不需要在String?上代表String的情况下进行额外的堆分配-它仅需要额外的内联存储位

答案 1 :(得分:-2)

到目前为止,我知道strings的值类型语义经过了很多优化(如写时复制等),但实际上它们被桥接到NSString类,因此它们在堆上分配。

值类型语义意味着从程序员的角度来看,当我们将值分配给另一个变量或传递给方法时,它们将被复制(在写优化时带有复制),我们可以在方法内部进行值突变,而源字符串不会受到影响,关键字不允许进行突变(由编译器检查)等等。

我建议您观看 GOTO 2016 会议上的 Mike Ash 探索Swift内存布局演示。

答案 2 :(得分:-3)

我们知道字符串是swift中的值类型,而值类型变量存储在堆栈内存分配中。

var str:String?
var str1: String = ""
在上述情况下,

都消耗堆栈内存。在str中可以分配nil值,但是在str1中,您永远不会分配nil值。