Search code examples
stringswiftstring-literals

Swift string via string literal vs initializer


In other languages such as Java, under the hood there is actually a difference between string obtained via string literal vs initializer. In Swift, are they equivalent under the hood?

e.g.

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

Refer to this SO post for info on differences between literal and object in Java.


Solution

  • The declarations are equivalent according to the Apple docs:

    Initializing an Empty String

    To create an empty String value as the starting point for building a longer string, either assign an empty string literal to a variable, or initialize a new String instance with initializer syntax:

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

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

    If we look at the assembly, we will see that the two constructors use identical instructions.

    string.swift:

    let str = String()
    let str2 = ""
    

    Compiled assembly (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
    

    Notice that the declarations for str and str2 have identical instructions:

    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
    

    You can learn more about String literals by reviewing the Apple's documentation.