Swift字符串通过字符串字面量和初始化器

25 浏览
0 Comments

Swift字符串通过字符串字面量和初始化器

在其他编程语言如Java中,字符串字面量和初始化器实际上在底层是有区别的。那么在Swift中,它们在底层是否等效?例如:\nvar string:String = \"\"\nvar string:String = String()\n\n请参考这个SO帖子了解Java中字面量和对象之间的区别。

0
0 Comments

Swift中的字符串可以通过字符串字面量或初始化器来创建。根据Apple文档,这两种声明是等价的。通过字符串字面量将一个空字符串赋值给一个变量,或者使用初始化器语法来初始化一个新的字符串实例,都可以创建一个空的String值作为构建较长字符串的起始点。换句话说,下面的代码是等价的:

var emptyString = "" // 空字符串字面量

var anotherEmptyString = String() // 初始化器语法

如果我们查看汇编代码,我们会发现这两种构造函数使用相同的指令。具体来说,下面的代码展示了通过字符串字面量和初始化器创建字符串的汇编代码:

let str = String()

let str2 = ""

编译后的汇编代码如下所示:

.section __TEXT,__text,regular,pure_instructions

.macosx_version_min 14, 3

.globl _main

.align 4, 0x90

_main:

.cfi_startproc

pushq %rbp

Ltmp0:

.cfi_def_cfa_offset 16

Ltmp1:

.cfi_offset %rbp, -16

movq %rsp, %rbp

Ltmp2:

.cfi_def_cfa_register %rbp

subq $16, %rsp

movq _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token4(%rip), %rax

movq _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func4(%rip), %rcx

xorl %edx, %edx

movl %edi, -4(%rbp)

movq %rax, %rdi

movq %rsi, -16(%rbp)

movq %rcx, %rsi

callq _swift_once

movq _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token5(%rip), %rdi

movq _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func5(%rip), %rax

xorl %r8d, %r8d

movl %r8d, %edx

movq __TZvOSs7Process5_argcVSs5Int32(%rip), %rcx

movl -4(%rbp), %r8d

movl %r8d, (%rcx)

movq %rax, %rsi

callq _swift_once

movq __TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__(%rip), %rax

movq -16(%rbp), %rcx

movq %rcx, (%rax)

callq __TFSSCfMSSFT_SS

leaq L___unnamed_1(%rip), %rdi

xorl %r8d, %r8d

movl %r8d, %esi

movl $1, %r8d

movq %rax, __Tv6string3strSS(%rip)

movq %rdx, __Tv6string3strSS+8(%rip)

movq %rcx, __Tv6string3strSS+16(%rip)

movl %r8d, %edx

callq __TFSSCfMSSFT21_builtinStringLiteralBp8byteSizeBw7isASCIIBi1__SS

xorl %r8d, %r8d

movq %rax, __Tv6string4str2SS(%rip)

movq %rdx, __Tv6string4str2SS+8(%rip)

movq %rcx, __Tv6string4str2SS+16(%rip)

movl %r8d, %eax

addq $16, %rsp

popq %rbp

retq

.cfi_endproc

.globl __Tv6string3strSS

.zerofill __DATA,__common,__Tv6string3strSS,24,3

.globl __Tv6string4str2SS

.zerofill __DATA,__common,__Tv6string4str2SS,24,3

.section __TEXT,__cstring,cstring_literals

L___unnamed_1:

.space 1

.no_dead_strip __Tv6string3strSS

.no_dead_strip __Tv6string4str2SS

.linker_option "-lswiftCore"

.section __DATA,__objc_imageinfo,regular,no_dead_strip

L_OBJC_IMAGE_INFO:

.long 0

.long 512

.subsections_via_symbols

我们可以注意到,str和str2的声明具有相同的指令:

xorl %r8d, %r8d

movl %r8d, %esi

movl $1, %r8d

movq %rax, __Tv6string3strSS(%rip)

movq %rdx, __Tv6string3strSS+8(%rip)

movq %rcx, __Tv6string3strSS+16(%rip)

movl %r8d, %edx

# ...

xorl %r8d, %r8d

movq %rax, __Tv6string4str2SS(%rip)

movq %rdx, __Tv6string4str2SS+8(%rip)

movq %rcx, __Tv6string4str2SS+16(%rip)

movl %r8d, %eax

这说明了通过字符串字面量和初始化器创建字符串的指令是相同的。根据编译后的汇编代码,这两种声明是等价的。

在Swift中,每次创建一个字符串,无论是使用"",String()还是String(""),重要的是字符串内部是什么。由于所有这些字符串内部都没有内容,因此它们在定义上是相同的。

值得一提的是,在Objective-C中,即使是引用类型的NSString,使用字面量和构造函数创建字符串也常常在底层是相同的。

总之,通过字符串字面量和初始化器创建字符串在Swift中是等价的,它们都会生成相同的汇编指令。

0