1
+ <!--
1
2
# Drop Flags
3
+ -->
2
4
5
+ # ドロップフラグ
6
+
7
+ <!--
3
8
The examples in the previous section introduce an interesting problem for Rust.
4
9
We have seen that it's possible to conditionally initialize, deinitialize, and
5
10
reinitialize locations of memory totally safely. For Copy types, this isn't
6
11
particularly notable since they're just a random pile of bits. However types
7
12
with destructors are a different story: Rust needs to know whether to call a
8
13
destructor whenever a variable is assigned to, or a variable goes out of scope.
9
14
How can it do this with conditional initialization?
15
+ -->
16
+
17
+ 前章の例では、 Rust における興味深い問題を紹介しました。
18
+ 状況によって、メモリの場所を初期化したり、初期化されていない状態に戻したり、
19
+ 再初期化したりすることを、完全に安全に行なうことが可能だということを
20
+ 確認してきました。 Copy を実装している型に関しては、メモリの場所にあるものは
21
+ 単なるビットのランダムな山であるため、これは特に重要なことではありません。
22
+ しかし、デストラクタを備えている型に関しては話が違います。 Rust は変数が代入されたときや、
23
+ あるいは変数がスコープを外れたときは毎回、デストラクタを呼ぶかを知る必要があります。
24
+ これを、状況に応じた初期化と共に、どのように行えばよいのでしょうか?
10
25
26
+ <!--
11
27
Note that this is not a problem that all assignments need worry about. In
12
28
particular, assigning through a dereference unconditionally drops, and assigning
13
29
in a `let` unconditionally doesn't drop:
30
+ -->
31
+
32
+ 全ての代入において心配する必要がある問題ではないことに注意してください。
33
+ 特に、参照外しを通した代入では、状況によらずドロップしますし、 ` let ` を使用した
34
+ 代入では、状況によらずドロップしません。
14
35
15
36
```
16
- let mut x = Box::new(0); // let makes a fresh variable, so never need to drop
37
+ let mut x = Box::new(0); // let によって新しい変数が生成されるので、ドロップの必要はありません
17
38
let y = &mut x;
18
- *y = Box::new(1); // Deref assumes the referent is initialized, so always drops
39
+ *y = Box::new(1); // 参照外しでは、参照される側の変数は初期化されていると見なされているため、この参照されている変数はいつもドロップします
19
40
```
20
41
42
+ <!--
21
43
This is only a problem when overwriting a previously initialized variable or
22
44
one of its subfields.
45
+ -->
23
46
47
+ これは、以前に初期化された変数や、その副フィールドの 1 つを上書きする時のみ問題となります。
48
+
49
+ <!--
24
50
It turns out that Rust actually tracks whether a type should be dropped or not
25
51
*at runtime*. As a variable becomes initialized and uninitialized, a *drop flag*
26
52
for that variable is toggled. When a variable might need to be dropped, this
27
53
flag is evaluated to determine if it should be dropped.
54
+ -->
55
+
56
+ 実際には Rust は* 実行時に* 、型がドロップされるべきかそうでないかを追っていると分かります。
57
+ 変数が初期化されたり、初期化されてない状態になったりすると、その変数に対する* ドロップフラグ* が
58
+ 切り替わります。もし変数がドロップされる必要があるかもしれない状況になると、
59
+ 本当にドロップされるべきかを決定するため、このフラグが評価されます。
28
60
61
+ <!--
29
62
Of course, it is often the case that a value's initialization state can be
30
63
statically known at every point in the program. If this is the case, then the
31
64
compiler can theoretically generate more efficient code! For instance, straight-
32
65
line code has such *static drop semantics*:
66
+ -->
67
+
68
+ 勿論、しばしば値の初期化に関する状態は、プログラムのどの地点においても
69
+ 知ることが出来ます。もしこれが本当なら、コンパイラは理論的には、
70
+ もっと効率的なコードを生成できます! 例えば、分岐のない真っ直ぐなコードは、
71
+ このような* 静的ドロップセマンティクス* を持っています。
33
72
34
73
``` rust
35
- let mut x = Box :: new (0 ); // x was uninit; just overwrite.
36
- let mut y = x ; // y was uninit; just overwrite and make x uninit.
37
- x = Box :: new (0 ); // x was uninit; just overwrite.
38
- y = x ; // y was init; Drop y, overwrite it, and make x uninit !
39
- // y goes out of scope; y was init; Drop y !
40
- // x goes out of scope; x was uninit; do nothing.
74
+ let mut x = Box :: new (0 ); // x は初期化されていないので、単に上書きします。
75
+ let mut y = x ; // y は初期化されていないので、単に上書きします。そして x を初期化前の状態にします。
76
+ x = Box :: new (0 ); // x は初期化されていないので、単に上書きします。
77
+ y = x ; // y は初期化されているので、 y をドロップし、上書きし、そして x を初期化前の状態にします !
78
+ // y はスコープを抜けました。 y は初期化されているので、 y をドロップします !
79
+ // x はスコープを抜けました。 x は初期化されていないので、何もしません。
41
80
```
42
81
82
+ <!--
43
83
Similarly, branched code where all branches have the same behavior with respect
44
84
to initialization has static drop semantics:
85
+ -->
86
+
87
+ 同じように、全ての分岐が初期化の点において、同一のことをする分岐があるコードでは、
88
+ 静的ドロップセマンティクスを持っています。
45
89
46
90
``` rust
47
91
# let condition = true ;
48
- let mut x = Box :: new (0 ); // x was uninit; just overwrite.
92
+ let mut x = Box :: new (0 ); // x は初期化されていないので、単に上書きします。
49
93
if condition {
50
- drop (x ) // x gets moved out; make x uninit.
94
+ drop (x ) // x はムーブされたので、 x を初期化前の状態にします。
51
95
} else {
52
96
println! (" {}" , x );
53
- drop (x ) // x gets moved out; make x uninit.
97
+ drop (x ) // x はムーブされたので、 x を初期化前の状態にします。
54
98
}
55
- x = Box :: new (0 ); // x was uninit; just overwrite.
56
- // x goes out of scope; x was init; Drop x !
99
+ x = Box :: new (0 ); // x は初期化されていない状態なので、単に上書きします。
100
+ // x はスコープを抜けました。 x は初期化されているので、 x をドロップします !
57
101
```
58
102
103
+ <!--
59
104
However code like this *requires* runtime information to correctly Drop:
105
+ -->
106
+
107
+ しかしながら以下のようなコードでは、正しくドロップするために実行時に情報が必要となります。
60
108
61
109
``` rust
62
110
# let condition = true ;
63
111
let x ;
64
112
if condition {
65
- x = Box :: new (0 ); // x was uninit; just overwrite.
113
+ x = Box :: new (0 ); // x は初期化されていないので、単に上書きします。
66
114
println! (" {}" , x );
67
115
}
68
- // x goes out of scope; x might be uninit;
69
- // check the flag !
116
+ // x はスコープを抜けました。 x は初期化されていないかもしれません。
117
+ // フラグを確認 !
70
118
```
71
119
120
+ <!--
72
121
Of course, in this case it's trivial to retrieve static drop semantics:
122
+ -->
123
+
124
+ 勿論この場合、静的ドロップセマンティクスを復活させるのは些細なことです。
73
125
74
126
``` rust
75
127
# let condition = true ;
@@ -79,5 +131,10 @@ if condition {
79
131
}
80
132
```
81
133
134
+ <!--
82
135
The drop flags are tracked on the stack and no longer stashed in types that
83
136
implement drop.
137
+ -->
138
+
139
+ ドロップフラグはスタック上で追跡され、ドロップを実装している型に
140
+ 隠されることはもはやありません。
0 commit comments