【Swift】String与Sbustring区别与联系

  • String 还是字符串,始终如一。
  • Substring 是string的切片。它们与base string共享内存buffer,并拥有一对范围索引。
  • StringProtocol 抽取出字符串的特征以及如何访问其功能,放进一个协议中。StringSubstring都遵循StringProtocol

【Swift】String与Sbustring区别与联系_第1张图片

字符串在不同的 Swift 版本中变化比较大。在 Swift 4 中,当需要从一个字符串中获取子串时,我们获取到的是 Substring 类型而不是一个 String 类型的值。为什么会这样?在 Swift 中,字符串是值类型。这意味着如果想从一个字符串中生成一个新的字符串,则需要做拷贝处理。这对于稳定性是有益的,但效率却不高。

从另一方面讲,一个 Substring 则是对其原始 String 的一个引用。它不需要做拷贝操作,所以更加高效。但是有另一个问题,假设我们要从一个很长的字符串中获取一个长度为 10 的 Substring,由于这个 Substring 会引用 String,那么只要 Substring 一直存在,String 就必须一直存在。所以,任何时候当处理完 Substring 后,需要将其转换为 String。

let myString = String(mySubstring)

这样只会拷贝子串,而原来的字符串可以被正确地回收。Substring 作为一种类型,本身即表示临时存在的。

在 Swift 4 另一个大的改进是字符串又成为集合了。这意味着在集合上的所有操作,也可以应用在字符串中(如下标、迭代字符、过滤等)。

Substring内部

substring的一部分魔法是重用了“parent” string的内存。你可以认为substring由base stringrange构成。

【Swift】String与Sbustring区别与联系_第2张图片

这意味着从一个8000字符的string上切一个100字符的substring不需要分配额外内存,也不用复制100个字符。

这也意味着你可能无意延长了你的base string的生命周期。如果你有一个超大字符串存了一整本小说,然后从其中切片了一个单词,那么只要substring还在,这个巨大的string就会一直阴魂不散。

那么到底substring内部是如何跟踪这些的呢?

public struct Substring {
  internal var _slice: RangeReplaceableBidirectionalSlice<String>

内部的 _slice属性保存了关于base string的所有信息:

// 仍然是 Substring 的代码
internal var _wholeString: String {
  return _slice._base
}
public var startIndex: Index { return _slice.startIndex }
public var endIndex: Index { return _slice.endIndex }

计算属性 _wholeString(返回原来完整的字符串),以及 startIndexendIndex (指出在string中切片的范围)只是简单的传递了内部切片属性的值。

你也能看到切片如何用 _base来保存原始string的信息。

参考:
https://www.jianshu.com/p/90adf8ce7b9a

https://blog.csdn.net/weixin_34054931/article/details/87979393

你可能感兴趣的:(swift,String,Substring)