【问题标题】:Swift string via string literal vs initializer通过字符串文字与初始值设定项的 Swift 字符串
【发布时间】:2015-09-20 17:12:29
【问题描述】:

在其他语言(例如 Java)中,实际上通过字符串文字和初始化程序获得的字符串之间存在差异。在 Swift 中,它们在底层是等价的吗?

例如

var string:String = ""
var string:String = String()

请参阅SO post,了解 Java 中文字和对象之间的差异。

【问题讨论】:

  • 它们都是一样的。 ""
  • String 是 Swift 中的结构体,而不是像 Java 这样的引用类型。到目前为止,我还没有发现一个可以产生影响的案例。

标签: string swift string-literals


【解决方案1】:

根据 Apple 文档,声明是等效的:

初始化一个空字符串

要创建一个空字符串值作为构建更长字符串的起点,可以将一个空字符串字面量分配给一个变量,或者使用初始化语法初始化一个新的字符串实例:

var emptyString = ""               // empty string literal
var anotherEmptyString = String()  // initializer syntax
// these two strings are both empty, and are equivalent to each other

参考:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html

如果我们查看程序集,我们会发现两个构造函数使用相同的指令。

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

您可以通过查看Apple's documentation 了解有关字符串文字的更多信息。

【讨论】:

  • 我的示例代码也来自 Apple 文档。虽然从使用的角度来看它是等价的,但文档并没有说明它是否在幕后是等价的,这是很常见的,因为大多数语言指南都没有达到那个水平。
  • 我现在不在我的构建机器上,但是如果您使用 -emit-assembly 标志编译一个包含两个声明的 swift 文件,它会告诉您声明是相同的。
  • @Boon 我知道,这就是我们谈论 Swift 的原因。在 Swift(而不是 Java)中,这些表达式的计算结果是相同的。 JAL 之前也通过查看编译的汇编代码证明了这一点
  • @Boon 每次创建""String()String("") 之类的字符串时,创建多少次并不重要,重要的是里面有什么:里面什么都没有所有这些字符串,所以它们的定义是相同的
  • 切向相关...即使在 Objective-C 中,NSString 是一个引用类型,字面量与构造函数在底层经常是相同的。 stackoverflow.com/a/31073079/2792531
猜你喜欢
  • 2011-01-03
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 2010-10-03
  • 2012-07-18
  • 2019-04-16
  • 2020-07-31
  • 1970-01-01
相关资源
最近更新 更多