Rob*_*b N 18 string immutability swift
在Swift编程语言中,在字符串部分String Mutability一节中,它说:
您
String可以通过将特定分配给变量(在这种情况下可以修改)或常量(在这种情况下不能修改)来指示特定是否可以修改(或变异):
并给出示例代码:
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"
let constantString = "Highlander"
constantString += " and another Highlander"
// this reports a compile-time error - a constant string cannot be modified”
Run Code Online (Sandbox Code Playgroud)
在下一段中,它声称"字符串是值类型".
我的问题:对我来说,这看起来不像是一个可变的字符串.它看起来像我在Java(或C#,Python和其他)中习惯的:具有可变变量绑定的不可变字符串对象.换句话说,有一个对象"Horse",然后它创建了一个新的String对象"Horse and carriage"并将其设置为相同的变量.而且由于无法区分对不可变对象的引用与值类型(对吗?)之间的区别,我想知道:为什么他们这样描述它?这些Swift字符串与它在Java中的方式有什么区别吗?(或C#,Python,Objective-C/NSString)
new*_*cct 15
在某种程度上,"可变"和"不可变"只在谈论引用类型时才有意义.如果您尝试将其扩展为值类型,则可以将所有值类型视为在功能上等同于"不可变"引用类型.
例如,考虑一种var类型Int.这可变吗?有些人可能会说,当然 - 您可以通过赋予它来改变其可见的"值" =.然而,同样可以的可以说var的NSNumber和NSString-您可以通过分配给它改变它的可见价值.但NSNumber和NSString被描述为不可变的类.
参考类型实际发生的是分配它们会导致变量(指针)指向新对象.旧的或新的对象本身都没有"改变",但由于它指向不同的对象,你"看到"一个新的值.
当我们说一个类是"可变的"时,我们的意思是它提供了一个API(方法或引用)来实际更改对象的内容.但我们怎么知道对象已经改变了?(而不是它是一个新对象?)这是因为我们可以对同一个对象有另一个引用,并且通过另一个引用可以看到通过一个引用对对象的更改.但是这些属性(指向具有指向同一对象的多个指针的不同对象)本身仅适用于引用类型.根据定义,值类型不能具有这样的"共享"(除非"值"的一部分是引用类型,例如Array),因此,对于值类型,"可变性"的后果不会发生.
因此,如果你创建一个包装整数的不可变类,它在操作上等同于Int- 在这两种情况下,更改变量值的唯一方法是assign(=).所以Int也应该同样被认为是"不可改变的".
Swift中的值类型稍微复杂一些,因为它们可以有方法,其中一些可以mutating.因此,如果您可以mutating在值类型上调用方法,它是否可变?但是,如果我们考虑mutating将值类型的方法调用为语法糖来为其分配一个全新的值(无论方法是否会将其变异),我们都可以克服这个问题.
在 Swift 中,结构体和枚举都是值类型:
\n\n\n\n\n事实上,Swift\xe2\x80\x94 中的所有基本类型整数、浮点数、布尔值、字符串、数组和字典\xe2\x80\x94 都是值类型,并在幕后实现为结构体。
\n
因此,字符串是一种在赋值时复制的值类型,并且不能有多个引用,但其底层字符数据存储在可共享的写入时复制缓冲区中。该结构的 API 参考String说:
\n\n\n尽管 Swift 中的字符串具有值语义,但字符串使用写入时复制策略将其数据存储在缓冲区中。然后,该缓冲区可以由字符串的不同副本共享。当多个字符串实例使用同一缓冲区时,字符串\xe2\x80\x99s 数据仅在突变时才被延迟复制。因此,任何变异操作序列中的第一个操作可能会花费 O(n) 时间和空间。
\n
因此,事实上,varvs.let声明了一个可变与不可变的绑定到看起来不可变的字符缓冲区。
var v1 = "Hi" // mutable\nvar v2 = v1 // assign/pass by value, i.e. copies the String struct\nv1.append("!") // mutate v1; does not mutate v2\n[v1, v2] // ["Hi!", "Hi"]\n\nlet c1 = v1 // immutable\nvar v3 = c1 // a mutable copy\n// c1.append("!") // compile error: "Cannot use mutating member on immutable value: \'c1\' is a \'let\' constant"\nv3 += "gh" // mutates v3, allocating a new character buffer if needed\nv3.append("?") // mutates v3, allocating a new character buffer if needed\n[c1, v3] // ["Hi", "High?"]\nRun Code Online (Sandbox Code Playgroud)\n\n这就像非最终变量与finalJava 字符串变量有两个问题。