为什么Swift中的字符串、数组、字典都变成了值类型

why string, array and dictionary in Swift changed to value type

在Objc中字符串、数组、字典都是引用类型,而在Swift中都是值类型

  1. 我想弄清楚背后的原因是什么,据我了解,无论是引用类型还是值类型,Objc和[=29中的对象都存在于堆中=].

  2. 是否为了简化编码而进行的更改?也就是说,如果它是引用类型,那么指向对象的指针可能不是 nil,因此需要检查指针和对象是否不是 nil 才能访问该对象。而如果它是值类型那么只需要检查对象本身?

  3. 但是在内存分配方面,值类型和引用类型是一样的吧?都分配了相同大小的内存?

感谢

我不知道,这是否是其背后的真实想法,但对它有一个历史的看法:

一开始,当您更改其中的项目时,数组副本按引用运行。当您更改数组的长度时,它按值表现。他们这样做是出于性能原因(较少的数组副本)。但是,这当然是,嗯,我怎么能巧妙地表达,嗯,Swift 根本很难,嗯,让我们称之为 "do not care about a good structure if you can win some performance, you probably never need" 方法。有人称之为写时复制,并没有更智能,因为 COW 是透明的,而这种行为并不透明。典型的Swift写法:用一个流行词,用它的方式,它适合Swift,不关心正确性。

后来数组得到了完整的复制行为,不再那么混乱了。 (你记得,Swift是为了可读性,显然在Swift的概念中,可读性是指"less characters to read",而不是"better understandable"。典型的Swift写法:使用流行语,使用它的方式,它适合 Swift,不要关心正确性。我已经提到了吗?)

所以,我想这仍然是性能加上可理解的行为可能导致性能下降。 (你会更好地知道你的代码何时需要一个副本,你仍然可以这样做,如果源数组是不可变的,你可以从 Cocoa 得到一个 0 操作。)当然,他们可以说:"Okay, by value was a mistake, we changed that." 但他们永远不会说。

但是,现在 Swift 中的数组行为一致。 Swift 的一大进步!也许你可以在阳光明媚的日子把它称为一种编程语言。

Objective-C 中的数组、字典等通常是可变的。这意味着当我将一个数组传递给另一个方法,然后在另一个方法的背后修改该数组时,会发生令人惊讶的(委婉地说)行为。

通过创建数组、字典等值类型,可以避免这种令人惊讶的行为。当您收到一个 Swift 数组时,您知道没有人会在您背后修改它。可以在您背后修改的对象是问题的主要来源。

实际上,Swift 编译器尽可能避免不必要的复制。所以即使说一个数组被正式复制了,也不代表真的被复制了。

Swift 团队在官方开发者论坛上非常活跃。因此,我假设由于您没有在那里询问,您更想知道社区更广泛的 "sense" 变化意味着什么,而不是技术实施细节。如果你想确切地了解"why",就去问他们:)

对我来说最有意义的解释是对象应该负责对应用程序的状态做出反应并更新它。值应该是您的应用程序的状态。换句话说,数组或字符串或字典(以及其他值类型)永远不应该负责响应用户输入或网络输入或错误条件等。对象处理这些并将结果数据存储到这些值中。

Swift 中的一个很棒的功能是值类型可以封装规则,这使得复杂的值类型(如字典或自定义类型如 Person,而不是简单的 Float)更加可行和逻辑,因为它们可以有功能。如果我将值类型 Person 写成一个结构,那么 Person 结构可以有一个函数来更新因婚姻等原因产生的姓名。这只与数据有关,而不与/管理/状态有关。对象仍将决定何时以及为何更新一个人的姓名,但是如何进行此操作的业务逻辑 safely/test-ably 可以包含在值类型本身中。因此,为您提供了一种增加隔离和降低复杂性的好方法。

除了前面的答案之外,在共享基于引用的集合类型时还需要考虑多线程问题,我们不必担心共享类型实例的值-基于并具有写时复制行为。即使在 iOS 设备上,多核也变得越来越多,因此它已成为 Swift 语言开发人员需要考虑的更多问题。