1+ <!--
12# Drop Flags
3+ -->
24
5+ # ドロップフラグ
6+
7+ <!--
38The examples in the previous section introduce an interesting problem for Rust.
49We have seen that it's possible to conditionally initialize, deinitialize, and
510reinitialize locations of memory totally safely. For Copy types, this isn't
611particularly notable since they're just a random pile of bits. However types
712with destructors are a different story: Rust needs to know whether to call a
813destructor whenever a variable is assigned to, or a variable goes out of scope.
914How can it do this with conditional initialization?
15+ -->
16+
17+ 前章の例では、 Rust における興味深い問題を紹介しました。
18+ 状況によって、メモリの場所を初期化したり、初期化されていない状態に戻したり、
19+ 再初期化したりすることを、完全に安全に行なうことが可能だということを
20+ 確認してきました。 Copy を実装している型に関しては、メモリの場所にあるものは
21+ 単なるビットのランダムな山であるため、これは特に重要なことではありません。
22+ しかし、デストラクタを備えている型に関しては話が違います。 Rust は変数が代入されたときや、
23+ あるいは変数がスコープを外れたときは毎回、デストラクタを呼ぶかを知る必要があります。
24+ これを、状況に応じた初期化と共に、どのように行えばよいのでしょうか?
1025
26+ <!--
1127Note that this is not a problem that all assignments need worry about. In
1228particular, assigning through a dereference unconditionally drops, and assigning
1329in a `let` unconditionally doesn't drop:
30+ -->
31+
32+ 全ての代入において心配する必要がある問題ではないことに注意してください。
33+ 特に、参照外しを通した代入では、状況によらずドロップしますし、 ` let ` を使用した
34+ 代入では、状況によらずドロップしません。
1435
1536```
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 によって新しい変数が生成されるので、ドロップの必要はありません
1738let y = &mut x;
18- *y = Box::new(1); // Deref assumes the referent is initialized, so always drops
39+ *y = Box::new(1); // 参照外しでは、参照される側の変数は初期化されていると見なされているため、この参照されている変数はいつもドロップします
1940```
2041
42+ <!--
2143This is only a problem when overwriting a previously initialized variable or
2244one of its subfields.
45+ -->
2346
47+ これは、以前に初期化された変数や、その副フィールドの 1 つを上書きする時のみ問題となります。
48+
49+ <!--
2450It turns out that Rust actually tracks whether a type should be dropped or not
2551*at runtime*. As a variable becomes initialized and uninitialized, a *drop flag*
2652for that variable is toggled. When a variable might need to be dropped, this
2753flag is evaluated to determine if it should be dropped.
54+ -->
55+
56+ 実際には Rust は* 実行時に* 、型がドロップされるべきかそうでないかを追っていると分かります。
57+ 変数が初期化されたり、初期化されてない状態になったりすると、その変数に対する* ドロップフラグ* が
58+ 切り替わります。もし変数がドロップされる必要があるかもしれない状況になると、
59+ 本当にドロップされるべきかを決定するため、このフラグが評価されます。
2860
61+ <!--
2962Of course, it is often the case that a value's initialization state can be
3063statically known at every point in the program. If this is the case, then the
3164compiler can theoretically generate more efficient code! For instance, straight-
3265line code has such *static drop semantics*:
66+ -->
67+
68+ 勿論、しばしば値の初期化に関する状態は、プログラムのどの地点においても
69+ 知ることが出来ます。もしこれが本当なら、コンパイラは理論的には、
70+ もっと効率的なコードを生成できます! 例えば、分岐のない真っ直ぐなコードは、
71+ このような* 静的ドロップセマンティクス* を持っています。
3372
3473``` 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 は初期化されていないので、何もしません。
4180```
4281
82+ <!--
4383Similarly, branched code where all branches have the same behavior with respect
4484to initialization has static drop semantics:
85+ -->
86+
87+ 同じように、全ての分岐が初期化の点において、同一のことをする分岐があるコードでは、
88+ 静的ドロップセマンティクスを持っています。
4589
4690``` rust
4791# let condition = true ;
48- let mut x = Box :: new (0 ); // x was uninit; just overwrite.
92+ let mut x = Box :: new (0 ); // x は初期化されていないので、単に上書きします。
4993if condition {
50- drop (x ) // x gets moved out; make x uninit.
94+ drop (x ) // x はムーブされたので、 x を初期化前の状態にします。
5195} else {
5296 println! (" {}" , x );
53- drop (x ) // x gets moved out; make x uninit.
97+ drop (x ) // x はムーブされたので、 x を初期化前の状態にします。
5498}
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 をドロップします !
57101```
58102
103+ <!--
59104However code like this *requires* runtime information to correctly Drop:
105+ -->
106+
107+ しかしながら以下のようなコードでは、正しくドロップするために実行時に情報が必要となります。
60108
61109``` rust
62110# let condition = true ;
63111let x ;
64112if condition {
65- x = Box :: new (0 ); // x was uninit; just overwrite.
113+ x = Box :: new (0 ); // x は初期化されていないので、単に上書きします。
66114 println! (" {}" , x );
67115}
68- // x goes out of scope; x might be uninit;
69- // check the flag !
116+ // x はスコープを抜けました。 x は初期化されていないかもしれません。
117+ // フラグを確認 !
70118```
71119
120+ <!--
72121Of course, in this case it's trivial to retrieve static drop semantics:
122+ -->
123+
124+ 勿論この場合、静的ドロップセマンティクスを復活させるのは些細なことです。
73125
74126``` rust
75127# let condition = true ;
@@ -79,5 +131,10 @@ if condition {
79131}
80132```
81133
134+ <!--
82135The drop flags are tracked on the stack and no longer stashed in types that
83136implement drop.
137+ -->
138+
139+ ドロップフラグはスタック上で追跡され、ドロップを実装している型に
140+ 隠されることはもはやありません。
0 commit comments