Are Swift “mutable” strings really mutable, or are they just like Java strings?

前端 未结 6 1438
独厮守ぢ
独厮守ぢ 2020-12-06 05:02

In The Swift Programming Language, in the section on Strings, subsection String Mutability, it says this:

You indicate whether a par

6条回答
  •  情话喂你
    2020-12-06 05:06

    In Swift, Structures and Enumerations Are Value Types:

    In fact, all of the basic types in Swift—integers, floating-point numbers, Booleans, strings, arrays and dictionaries—are value types, and are implemented as structures behind the scenes.

    So a string is a value type that gets copied on assignment and cannot have multiple references, but its underlying character data is stored in a shareable, copy-on-write buffer. The API reference for the String struct says:

    Although strings in Swift have value semantics, strings use a copy-on-write strategy to store their data in a buffer. This buffer can then be shared by different copies of a string. A string’s data is only copied lazily, upon mutation, when more than one string instance is using the same buffer. Therefore, the first in any sequence of mutating operations may cost O(n) time and space.

    So indeed, var vs. let declares a mutable vs. immutable binding to a character buffer that appears immutable.

    var v1 = "Hi"      // mutable
    var v2 = v1        // assign/pass by value, i.e. copies the String struct
    v1.append("!")     // mutate v1; does not mutate v2
    [v1, v2]           // ["Hi!", "Hi"]
    
    let c1 = v1        // immutable
    var v3 = c1        // a mutable copy
    // c1.append("!")  // compile error: "Cannot use mutating member on immutable value: 'c1' is a 'let' constant"
    v3 += "gh"         // mutates v3, allocating a new character buffer if needed
    v3.append("?")     // mutates v3, allocating a new character buffer if needed
    [c1, v3]           // ["Hi", "High?"]
    

    This is like non-final vs. final Java String variables with two wrinkles.

    1. With a mutable binding you may call mutating methods. Since there can't be any aliasing to a value type, you can't tell whether a mutating method actually modifies the character buffer or reassigns to the String variable, except for the performance impact.
    2. The implementation can optimize mutating operations by mutating a character buffer in place when it's used by only one String instance.

提交回复
热议问题