@@ -16,7 +16,7 @@ Swift 会要求修改内存的代码拥有对被修改区域的独占访问权
16
16
17
17
## 理解内存访问冲突
18
18
19
- 在做为变量赋值、给函数传参这样的事情时 ,你的代码会访问内存。举个例子,下面的代码包含了一次读操作和一次写操作:
19
+ 在进行变量赋值、函数传参这样的操作时 ,你的代码会访问内存。举个例子,下面的代码包含了一次读操作和一次写操作:
20
20
21
21
``` swift
22
22
// 向 one 所在的内存区域发起一次写操作
@@ -44,7 +44,7 @@ print("We're number \(one)!")
44
44
or else I'm going to keep getting "We are Number One" stuck in my head.
45
45
-->
46
46
47
- 当代码中的不同部分试图访问同一块内存区域时 ,访问冲突就有可能出现。对一块内存区域的同时访问可能导致程序出现无法预测或不稳定的行为。Swift 中有许多修改数值的方式,其中一些会横跨多行代码,这意味着修改某个数值的过程本身也有可能产生对此数值的访问。
47
+ 当多个不同地方的代码试图访问同一块内存区域时 ,访问冲突就有可能出现。对一块内存区域的同时访问可能导致程序出现无法预测或不稳定的行为。Swift 中有许多修改数值的方式,其中一些会横跨多行代码,这意味着修改某个数值的过程本身也有可能产生对此数值的访问。
48
48
49
49
要理解这个问题,你可以尝试想象一下在纸上更新一个预算表的流程。更新预算表分为两步:第一步你需要先添加每个预算项目的名字和数额,第二步才是更新预算总额。在整个更新流程的之前及之后,你可以从预算中读取任何信息,而这些信息都是正确的,就像下图所示一样。
50
50
@@ -118,7 +118,7 @@ print(myNumber)
118
118
119
119
一个函数会对它所有的 in-out 参数保持长时写访问。in-out 参数的写访问会在所有非 in-out 参数处理完之后开始,直到函数执行完毕为止。如果存在多个 in-out 参数,则写访问的开始顺序和参数的排列顺序一致。
120
120
121
- 这种长期保持的写访问带来的问题是 :即便作用域和访问权限规则允许,你也不能再访问以 in-out 形式传入的原始变量。这是因为任何访问原始变量的行为都会造成冲突,例如:
121
+ 这种长时保持的写访问带来的问题是 :即便作用域和访问权限规则允许,你也不能再访问以 in-out 形式传入的原始变量。这是因为任何访问原始变量的行为都会造成冲突,例如:
122
122
123
123
``` swift
124
124
var stepSize = 1
@@ -186,7 +186,7 @@ stepSize = copyOfStepSize
186
186
187
187
由于你在调用 ` increment(_:) ` 前复制了 ` stepSize ` ,显然 ` copyOfStepSize ` 会以当前 ` stepSize ` 的值增加。读访问在写访问开始前就结束了,所以不会产生冲突。
188
188
189
- 对于 in-out 参数保持长期写访问的另一个后果是 ,往同一个函数的多个 in-out 参数里传入同一个变量也会产生冲突。例如:
189
+ 对于 in-out 参数保持长时写访问的另一个后果是 ,往同一个函数的多个 in-out 参数里传入同一个变量也会产生冲突。例如:
190
190
191
191
``` swift
192
192
func balance (_ x : inout Int , _ y : inout Int ) {
@@ -251,7 +251,7 @@ balance(&playerOneScore, &playerOneScore)
251
251
because, under the hood, that's exactly what happens.
252
252
-->
253
253
254
- 一个结构体的变值方法会在其被调用期间保持对于 ` self ` 的长时写访问。想象这样一个游戏:其中每个玩家都有一定的生命值,受到伤害时会减少;玩家还会有能量值,会在玩家使用特殊技能时减少。
254
+ 一个结构体的变值(mutating)方法会在其被调用期间保持对于 ` self ` 的长时写访问。想象这样一个游戏:其中每个玩家都有一定的生命值,受到伤害时会减少;玩家还会有能量值,会在玩家使用特殊技能时减少。
255
255
256
256
``` swift
257
257
struct Player {
@@ -357,7 +357,7 @@ oscar.shareHealth(with: &oscar)
357
357
358
358
## 属性访问冲突
359
359
360
- 结构体、元组、枚举这样的类型是由多个独立的值构成的(例如结构题的属性 、元组的元素)。它们都是值类型,所以修改值的任何一部分都是对于整个值的修改。这意味着对于其中任何一个属性的读或写访问,都需要对于整个值的访问。例如,对于元组元素的重叠写访问会造成冲突:
360
+ 结构体、元组、枚举这样的类型是由多个独立的值构成的(例如结构体的属性 、元组的元素)。它们都是值类型,所以修改值的任何一部分都是对于整个值的修改。这意味着对于其中任何一个属性的读或写访问,都需要对于整个值的访问。例如,对于元组元素的重叠写访问会造成冲突:
361
361
362
362
``` swift
363
363
var playerInformation = (health : 10 , energy : 20 )
@@ -383,7 +383,7 @@ balance(&playerInformation.health, &playerInformation.energy)
383
383
```
384
384
-->
385
385
386
- 在上方的示例中 ,因为出现了对于 ` playerInformation ` 的重叠写访问,对元组中的元素调用 ` balance(_:_:) ` 就会产生冲突。` playerInformation.health ` 和 ` playerInformation.energy ` 都被作为 in-out 参数被传入了,这意味着 ` balance(_:_:) ` 在执行期间需要保持对它们的写访问,而这又意味着 ` balance(_:_:) ` 需要保持两次对 ` playerInformation ` 整体的重叠写访问,这样一来就发生了访问冲突。
386
+ 在上面的示例中 ,因为出现了对于 ` playerInformation ` 的重叠写访问,对元组中的元素调用 ` balance(_:_:) ` 就会产生冲突。` playerInformation.health ` 和 ` playerInformation.energy ` 都被作为 in-out 参数被传入了,这意味着 ` balance(_:_:) ` 在执行期间需要保持对它们的写访问,而这又意味着 ` balance(_:_:) ` 需要保持两次对 ` playerInformation ` 整体的重叠写访问,这样一来就发生了访问冲突。
387
387
388
388
下方的代码展示了对一个存储在全局变量中的结构体的重叠写访问,这会导致相同的错误。
389
389
@@ -414,7 +414,7 @@ balance(&holly.health, &holly.energy) // 错误
414
414
```
415
415
-->
416
416
417
- 在实践中,大多数时候对于结构体属性的重叠访问是安全的。举个例子,如果上方例子中的变量 ` holly ` 是一个本地变量而非全局变量,编译器可以「证明」对于该结构体的属性的重叠访问是安全的 :
417
+ 在实践中,大多数时候对于结构体属性的重叠访问是安全的。举个例子,如果上方例子中的变量 ` holly ` 是一个本地变量而非全局变量,编译器可以证明对于该结构体的属性的重叠访问是安全的 :
418
418
419
419
``` swift
420
420
func someFunction () {
0 commit comments