迅速,字符串是结构类型,因此值将存储在堆栈内存中,而不是堆中。
假设我们声明一个字符串:
let a = ""
let b = "o"
这是一个空字符串,但是分配了一些内存。我需要知道给定一个空字符串和一个带有1的字符串的内存有什么区别。
如果我们说:-
var str:String?
var str: String = ""
我需要看到的是,通过绘图在内存布局上的差异。 (堆栈/堆)。
我试图在Google上找到它,但是没有地方找不到它的内存布局。
答案 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值。