我正在浏览文档,我找到了StaticString.它指出:
一个简单的字符串,用于表示"在编译时可以识别"的文本.
我原本以为它String具有与NSString编译时相同的行为,但看起来我错了.所以我的问题是我们何时应该使用StaticString而不是a String,唯一的区别是StaticString编译时是否已知?
我找到的一件事是
var a: String = "asdf" //"asdf"
var b: StaticString = "adsf" //{(Opaque Value), (Opaque Value), (Opaque Value)}
sizeofValue(a) //24
sizeofValue(b) //17
Run Code Online (Sandbox Code Playgroud)
所以看起来StaticString内存占用少了一点.
似乎StaticString可以容纳字符串文字。您不能为其分配类型变量,String也不能对其进行突变(+=例如,使用)。
“在编译时知道”并不意味着变量的值将在编译时确定,而分配给它的任何值在编译时都是已知的。
考虑一下这个有效的例子:
var str: StaticString
for _ in 1...10 {
switch arc4random_uniform(3) {
case 0: str = "zero"
case 1: str = "one"
case 2: str = "two"
default: str = "default"
}
print(str)
}
Run Code Online (Sandbox Code Playgroud)
每当您可以向Swift提供有关如何使用变量的更多信息时,它都可以使用该变量优化代码。通过将变量限制为StaticString,Swift知道该变量不会被突变,因此它可能能够更有效地存储它,或者更有效地访问各个字符。
实际上,StaticString可以只用一个地址指针和一个长度来实现。它指向的地址只是静态代码中定义字符串的位置。A StaticString不需要被引用计数,因为它(不)存在于堆中。它既没有分配也没有释放,因此不需要引用计数。
“在编译时知道”是非常严格的。即使这样也不起作用:
let str: StaticString = "hello " + "world"
Run Code Online (Sandbox Code Playgroud)
失败并出现错误:
错误:“字符串”不可转换为“ StaticString”
StaticString在编译时是可知的。这可以导致优化。例子:
编辑:这部分不起作用,请参阅下面的编辑
假设您有一个函数,可以Int为String您在编译时定义的一些常量计算一些值。
let someString = "Test"
let otherString = "Hello there"
func numberForString(string: String) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
let some = numberForString(someString)
let other = numberForString(otherString)
Run Code Online (Sandbox Code Playgroud)
像这样,当在程序中真正调用该函数时,例如应用程序启动时,该函数将使用“Test”和“Hello there”来执行。肯定是在运行时。但是,如果您更改您的功能以采取StaticString
func numberForString(string: StaticString) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
Run Code Online (Sandbox Code Playgroud)
编译器知道传入的在StaticString编译时是可知的,所以猜猜它是做什么的?它在编译时运行该函数(这真是太棒了!)。我曾经读过一篇关于这个的文章,作者检查了生成的程序集,他实际上找到了已经计算过的数字。
正如您所看到的,这在某些情况下很有用,就像提到的那样,不会降低可以在编译时完成的工作的运行时性能。
编辑:Dániel Nagy和我进行了交谈。矿的上述例子中不起作用,因为该函数stringValue的StaticString无法在编译时是已知的(因为它返回一个String)。这是一个更好的例子:
func countStatic(string: StaticString) -> Int {
return string.byteSize // Breakpoint here
}
func count(string: String) -> Int {
return string.characters.count // Breakpoint here
}
let staticString : StaticString = "static string"
let string : String = "string"
print(countStatic(staticString))
print(count(string))
Run Code Online (Sandbox Code Playgroud)
在发布版本中,仅触发第二个断点,而如果您将第一个函数更改为
func countStatic(string: StaticString) -> Int {
return string.stringValue.characters.count // Breakpoint here
}
Run Code Online (Sandbox Code Playgroud)
两个断点都被触发。
显然有一些方法可以在编译时完成,而其他方法则不能。我想知道编译器实际上是如何计算出来的。
| 归档时间: |
|
| 查看次数: |
5867 次 |
| 最近记录: |