Empty Swift string Memory allocation Layout (Stack/ Heap allocation)

String is a very complicated beast. It has many different underlying representations, including:

  • String literals, which are stored as constants in the binary

  • Small strings, which can store up to 15 UTF-8 code units inline on the stack (on x86 at least)

  • "Native" strings (i.e strings that haven't been bridged to Objective-C), which are stored in a tail-allocated heap buffer

  • "Foreign" strings from Obj-C which can be represented by a tagged pointer or heap allocated NSString object

  • "Shared" strings which can represent a Swift string literal as a heap allocated Obj-C object

If you want to dive into the nitty gritty details, you can start at StringObject.swift, which has a bunch of comments explaining some of the layout details.

To answer your question about the examples you give:


let a = ""

An empty string has a canonical small string representation which is stored inline on the stack.


let b = "o"

A string literal is stored as a constant in the binary. Therefore no heap allocation is required – a pointer to the string's address in the binary is all that's required.

But even if this wasn't a constant string, for example it was created by:

let o = "O".lowercased()

Then it can still be represented as a small string, which is stored inline on the stack.


var str: String?

String has an extra inhabitant (at least on x86), meaning that String? can share the same layout as String. The value nil is represented by one of the extra inhabitant bit patterns.

But even if String didn't have an extra inhabitant, no additional heap allocation would be required to represent String? over String – it would only require an additional bit of inline storage.