在其他语言比如Java中,字符串字面值和初始化器获得的字符串其实是有区别的。在Swift中,它们在底层是等效的吗?
例如:
var string:String = ""
var string:String = String()
请参考这篇SO帖子了解Java中文字符与字符串对象之间的区别。
在其他语言比如Java中,字符串字面值和初始化器获得的字符串其实是有区别的。在Swift中,它们在底层是等效的吗?
例如:
var string:String = ""
var string:String = String()
请参考这篇SO帖子了解Java中文字符与字符串对象之间的区别。
据苹果文档,这些声明是等价的:
初始化空字符串
为了创建一个空字符串作为构建更长字符串的起点,可以将一个空字符串字面量赋值给一个变量,或使用初始化语法初始化一个新的String实例:
var emptyString = "" // empty string literal
var anotherEmptyString = String() // initializer syntax
// these two strings are both empty, and are equivalent to each other
如果我们查看汇编代码,会发现这两个构造函数使用相同的指令。
string.swift:
let str = String()
let str2 = ""
汇编代码(swiftc -emit-assembly string.swift
编译):
.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@GOTPCREL(%rip), %rax
movq _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func4@GOTPCREL(%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@GOTPCREL(%rip), %rdi
movq _globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func5@GOTPCREL(%rip), %rax
xorl %r8d, %r8d
movl %r8d, %edx
movq __TZvOSs7Process5_argcVSs5Int32@GOTPCREL(%rip), %rcx
movl -4(%rbp), %r8d
movl %r8d, (%rcx)
movq %rax, %rsi
callq _swift_once
movq __TZvOSs7Process11_unsafeArgvGVSs20UnsafeMutablePointerGS0_VSs4Int8__@GOTPCREL(%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
您可以通过查看苹果文档来了解有关字符串字面量的更多信息。
-emit-assembly
标志编译一个包含这两个声明的Swift文件,它将向你展示这些声明是相同的。 - JAL""
、String()
或 String("")
这样的字符串时,重要的不是你创建了多少次,而是里面的内容:所有这些字符串都没有任何内容,因此它们在定义上是相同的。 - KametrixomNSString
是一个引用类型,在底层上,使用字面量和构造函数经常是相同的。与此有些关联。 - nhgrif
String
在 Swift 中是一个结构体,而不像 Java 一样是引用类型。到目前为止,我还没有发现任何情况下它会有所区别。 - Code Different