39
39
<!-- is _done at compile time_. You do not pay any run-time cost for any of these -->
40
40
<!-- features. -->
41
41
Rustは安全性とスピートに焦点を合わせます。
42
- Rustはそれらの目標をたくさんの「ゼロコスト抽象化」を通じて成し遂げます。それは、Rustでは抽象化を機能させるためのコストをできる限り小さくすることを意味します。
42
+ Rustはそれらの目標を、様々な「ゼロコスト抽象化」を通じて成し遂げます。
43
+ それは、Rustでは抽象化を機能させるためのコストをできる限り小さくすることを意味します。
43
44
所有権システムはゼロコスト抽象化の主な例です。
44
45
このガイドの中で話すであろう解析の全ては _ コンパイル時に行われます_ 。
45
46
それらのどの機能に対しても実行時のコストは全く掛かりません。
@@ -54,9 +55,11 @@ Rustはそれらの目標をたくさんの「ゼロコスト抽象化」を通
54
55
<!-- rules of the ownership system for a period of time, they fight the borrow -->
55
56
<!-- checker less and less. -->
56
57
しかし、このシステムはあるコストを持ちます。それは学習曲線です。
57
- 多くの新しいRustのユーザは「借用チェッカとの戦い」と好んで呼ばれるものを経験します。そこではRustコンパイラが開発者が正しいと考えるプログラムをコンパイルすることを拒絶します。
58
+ 多くのRust入門者は、私たちが「借用チェッカとの戦い」と呼ぶものを経験します。
59
+ そこではRustコンパイラが、開発者が正しいと考えるプログラムをコンパイルすることを拒絶します。
58
60
所有権がどのように機能するのかについてのプログラマのメンタルモデルがRustの実装する実際のルールにマッチしないため、これはしばしば起きます。
59
- しかし、よいニュースがあります。より経験豊富なRustの開発者は次のことを報告します。一度彼らが所有権システムのルールとともにしばらく仕事をすれば、彼らが借用チェッカと戦うことは少なくなっていくということです。
61
+ しかし、よいニュースがあります。より経験豊富なRustの開発者は次のことを報告します。
62
+ それは、所有権システムのルールと共にしばらく仕事をすれば、借用チェッカと戦うことは次第に少なくなっていく、というものです。
60
63
61
64
<!-- With that in mind, let’s learn about ownership. -->
62
65
それを念頭に置いて、所有権について学びましょう。
@@ -77,27 +80,45 @@ fn foo() {
77
80
}
78
81
```
79
82
80
- <!-- When `v` comes into scope, a new [`Vec<T>`][vect ] is created. In this case, the -->
81
- <!-- vector also allocates space on [the heap][heap], for the three elements. When -->
82
- <!-- `v` goes out of scope at the end of `foo()`, Rust will clean up everything -->
83
- <!-- related to the vector, even the heap-allocated memory. This happens -->
84
- <!-- deterministically, at the end of the scope. -->
85
- ` v ` がスコープに入るとき、新しい [ ` Vec<T> ` ] [ vect ] が作られます 。
86
- この場合、ベクタも3つの要素のために [ ヒープ ] [ heap ] に空間を割り当てます 。
87
- ` foo() ` の最後で ` v ` がスコープから外れるとき、Rustはベクタに関連するもの全てを取り除くでしょう。それがヒープ割当てのメモリであってもです 。
83
+ <!-- When `v` comes into scope, a new [vector][vectors ] is created on [the stack][stack], -->
84
+ <!-- and it allocates space on [the heap][heap] for its elements. When `v` goes out -->
85
+ <!-- of scope at the end of `foo()`, Rust will clean up everything related to the -->
86
+ <!-- vector, even the heap-allocated memory. This happens deterministically, at the -->
87
+ <!-- end of the scope. -->
88
+ ` v ` がスコープに入るとき、新しい [ ベクタ ] [ vectors ] が [ スタック ] [ stack ] 上に作られ、要素を格納するために [ ヒープ ] [ heap ] に空間を割り当てます 。
89
+ ` foo() ` の最後で ` v ` がスコープから外れるとき、Rustはベクタに関連するもの全てを取り除くでしょう 。
90
+ それがヒープ割り当てのメモリであってもです 。
88
91
これはスコープの最後で決定的に起こります。
89
92
90
- [ vect ] : ../std/vec/struct.Vec.html
93
+ <!-- We'll cover [vectors] in detail later in this chapter; we only use them -->
94
+ <!-- here as an example of a type that allocates space on the heap at runtime. They -->
95
+ <!-- behave like [arrays], except their size may change by `push()`ing more -->
96
+ <!-- elements onto them. -->
97
+ <!-- 訳注:"We'll cover [vectors] in detail later..." となっていますが、 -->
98
+ <!-- ベクタはこのセクションより前に説明されていますので、それに合わせて訳を変更しました。 -->
99
+ [ ベクタ] [ vectors ] については、前のセクションで説明済みですが、簡単に復習しましょう。
100
+ ここではベクタを、実行時にヒープに空間を割り当てる型の例として用いています。
101
+ ベクタは [ 配列] [ arrays ] のように振る舞いますが、追加の要素を ` push() ` するとサイズが変わるところは違います。
102
+
103
+ <!-- Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type -->
104
+ <!-- `Vec<i32>`. We'll cover generics in detail later in this chapter. -->
105
+ ベクタは [ ジェネリクス型] [ generics ] ` Vec<T> ` を持ちますので、この例における ` v ` は ` Vec<i32> ` 型になるでしょう。
106
+ ジェネリクスについては、この章の後の方で詳しく説明します。
107
+
108
+ [ arrays ] : primitive-types.html#arrays
109
+ [ vectors ] : vectors.html
91
110
[ heap ] : the-stack-and-the-heap.html
111
+ [ stack ] : the-stack-and-the-heap.html#the-stack
92
112
[ bindings ] : variable-bindings.html
113
+ [ generics ] : generics.html
93
114
94
115
<!-- # Move semantics -->
95
116
# ムーブセマンティクス
96
117
97
118
<!-- There’s some more subtlety here, though: Rust ensures that there is _exactly -->
98
119
<!-- one_ binding to any given resource. For example, if we have a vector, we can -->
99
120
<!-- assign it to another binding: -->
100
- しかし、ここではもっと微妙なことがあります 。それは、Rustは与えられたリソースに対する束縛が _ 1つだけ_ あるということを保証するということです 。
121
+ しかし、ここではもっと些細に見えることがあります 。それは、Rustは与えられたリソースに対する束縛が _ 1つだけ_ あることを保証するというものです 。
101
122
例えば、もしベクタがあれば、それを別の束縛に割り当てることはできます。
102
123
103
124
``` rust
@@ -118,7 +139,7 @@ println!("v[0] is: {}", v[0]);
118
139
```
119
140
120
141
<!-- It looks like this: -->
121
- それはこのように見えます 。
142
+ こんな感じのエラーです 。
122
143
123
144
``` text
124
145
error: use of moved value: `v`
@@ -148,44 +169,106 @@ println!("v[0] is: {}", v[0]);
148
169
<!-- special annotation here, it’s the default thing that Rust does. -->
149
170
「use of moved value」という同じエラーです。
150
171
所有権を何か別のものに転送するとき、参照するものを「ムーブした」と言います。
151
- ここでは特別な種類の注釈を必要としません 。
152
- それはRustの行うデフォルトの動作です 。
172
+ これは特別な種類の注釈なしに行われます 。
173
+ つまりRustのデフォルトの動作です 。
153
174
154
175
<!-- ## The details -->
155
176
## 詳細
156
177
157
178
<!-- The reason that we cannot use a binding after we’ve moved it is subtle, but -->
158
- <!-- important. When we write code like this: -->
159
- 束縛をムーブした後ではそれを使うことができないということの理由は微妙ですが重要です。
160
- このようなコードを書いたとします。
179
+ <!-- important. -->
180
+ 束縛をムーブした後で、それを使うことができないと言いました。
181
+ その理由は、ごく詳細かもしれませんが、とても重要です。
182
+
183
+ <!-- When we write code like this: -->
184
+ このようなコードを書いた時、
185
+
186
+ ``` rust
187
+ let x = 10 ;
188
+ ```
189
+
190
+ <!-- Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit -->
191
+ <!-- pattern representing the value of 10 to the allocated memory and binds the -->
192
+ <!-- variable name x to this memory region for future reference. -->
193
+ Rustは [ スタック] [ sh ] 上に整数 [ i32] のためのメモリを割り当て、そこに、10という値を表すビットパターンをコピーします。
194
+ そして後から参照できるよう、変数名xをこのメモリ領域に束縛します。
195
+
196
+ <!-- Now consider the following code fragment: -->
197
+ 今度は、こんなコード片について考えてみましょう。
161
198
162
199
``` rust
163
200
let v = vec! [1 , 2 , 3 ];
164
201
165
- let v2 = v ;
202
+ let mut v2 = v ;
203
+ ```
204
+
205
+ <!-- The first line allocates memory for the vector object `v` on the stack like -->
206
+ <!-- it does for `x` above. But in addition to that it also allocates some memory -->
207
+ <!-- on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address -->
208
+ <!-- of this heap allocation to an internal pointer, which is part of the vector -->
209
+ <!-- object placed on the stack (let's call it the data pointer). -->
210
+ <!-- 訳注:ここで "data pointer" という言葉を導入してますが、後で使っていないので、訳は省きました。-->
211
+ <!-- 訳注:allocation ですが、「割り当て」だと不自然な所は、「領域(region)」と訳しました。 -->
212
+ 最初の行では、先ほどの ` x ` と同様に、ベクタオブジェクト ` v ` のために、スタック上にメモリを割り当てます。
213
+ しかし、これに加えて、実際のデータ( ` [1, 2, 3] ` )のために、 [ ヒープ] [ sh ] 上にもメモリを割り当てます。
214
+ スタック上のベクタオブジェクトの中にはポインタがあり、Rustはいま割り当てたヒープのアドレスをそこへコピーします。
215
+
216
+ <!-- It is worth pointing out (even at the risk of stating the obvious) that the -->
217
+ <!-- vector object and its data live in separate memory regions instead of being a -->
218
+ <!-- single contiguous memory allocation (due to reasons we will not go into at -->
219
+ <!-- this point of time). These two parts of the vector (the one on the stack and -->
220
+ <!-- one on the heap) must agree with each other at all times with regards to -->
221
+ <!-- things like the length, capacity etc. -->
222
+ すでに分かりきっているかもしれませんが、念のためここで確認しておきたいのは、ベクタオブジェクトとそのデータは、それぞれが別のメモリ領域に格納されていることです。
223
+ 決してそれらは、1つの連続したメモリ領域に置かれているわけではありません(その理由についての詳細は、いまは省きます)。
224
+ そして、ベクタにおけるこれら2つの部分(スタック上のものと、ヒープ上のもの)は、要素数やキャパシティ(容量)などについて、常にお互いの間で一貫性が保たれている必要があります。
225
+
226
+ <!-- When we move `v` to `v2`, Rust actually does a bitwise copy of the vector -->
227
+ <!-- object `v` into the stack allocation represented by `v2`. This shallow copy -->
228
+ <!-- does not create a copy of the heap allocation containing the actual data. -->
229
+ <!-- Which means that there would be two pointers to the contents of the vector -->
230
+ <!-- both pointing to the same memory allocation on the heap. It would violate -->
231
+ <!-- Rust’s safety guarantees by introducing a data race if one could access both -->
232
+ <!-- `v` and `v2` at the same time. -->
233
+ ` v ` を ` v2 ` にムーブするときRustが実際に行うのは、ビット単位のコピーを使って、ベクタオブジェクト ` v ` が示すスタック領域の情報を、 ` v2 ` が示すスタック領域へコピーすることです。
234
+ この浅いコピーでは、実際のデータを格納しているヒープ領域はコピーしません。
235
+ これはベクタに格納されたデータとして、ヒープ上の同一のメモリ領域を指すポインタが、2つできてしまうことを意味します。
236
+ もし誰かが ` v ` と ` v2 ` に同時にアクセスしたら?
237
+ これはデータ競合を持ち込むことになり、Rustの安全性保証に違反するでしょう。
238
+
239
+ <!-- For example if we truncated the vector to just two elements through `v2`: -->
240
+ 例えば ` v2 ` を通して、ベクタを2要素分、切り詰めたとしましょう。
241
+
242
+ ``` rust
243
+ # let v = vec! [1 , 2 , 3 ];
244
+ # let mut v2 = v ;
245
+ v2 . truncate (2 );
166
246
```
167
247
168
- <!-- The first line allocates memory for the vector object, `v`, and for the data it -->
169
- <!-- contains. The vector object is stored on the [stack][sh] and contains a pointer -->
170
- <!-- to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`, -->
171
- <!-- it creates a copy of that pointer, for `v2`. Which means that there would be two -->
172
- <!-- pointers to the content of the vector on the heap. It would violate Rust’s -->
173
- <!-- safety guarantees by introducing a data race. Therefore, Rust forbids using `v` -->
174
- <!-- after we’ve done the move. -->
175
- 最初の行はベクタオブジェクト ` v ` とそれの含むデータのためのメモリを割り当てます。
176
- ベクタオブジェクトは [ スタック] [ sh ] に保存され、 [ ヒープ] [ sh ] に保存された内容( ` [1, 2, 3] ` )へのポインタを含みます。
177
- ` v ` を ` v2 ` にムーブするとき、それは ` v2 ` のためにそのポインタのコピーを作ります。
178
- それは、ヒープ上のベクタの内容へのポインタが2つあることを意味します。
179
- それはデータ競合を持ち込むことでRustの安全性保証に違反するでしょう。
180
- そのため、Rustはムーブを終えた後の ` v ` の使用を禁止するのです。
248
+ <!-- and `v1` were still accessible we'd end up with an invalid vector since `v1` -->
249
+ <!-- would not know that the heap data has been truncated. Now, the part of the -->
250
+ <!-- vector `v1` on the stack does not agree with the corresponding part on the -->
251
+ <!-- heap. `v1` still thinks there are three elements in the vector and will -->
252
+ <!-- happily let us access the non existent element `v1[2]` but as you might -->
253
+ <!-- already know this is a recipe for disaster. Especially because it might lead -->
254
+ <!-- to a segmentation fault or worse allow an unauthorized user to read from -->
255
+ <!-- memory to which they don't have access. -->
256
+ もしまだ ` v1 ` にアクセスできたとしたら、` v1 ` はヒープデータが切り詰められたことを知らないので、不正なベクタを提供することになってしまいます。
257
+ ここでスタック上の ` v1 ` は、ヒープ上で対応する相手と一貫性が取れていません。
258
+ ` v1 ` はベクタにまだ3つの要素があると思っているので、もし私たちが存在しない要素 ` v1[2] ` にアクセスしようとしたら、喜んでそうさせるでしょう。
259
+ しかし、すでにお気づきの通り、特に次のような理由から大惨事に繋がるかもしれません。
260
+ これはセグメンテーション違反を起こすかもしれませんし、最悪の場合、権限を持たないユーザーが、本来アクセスできないはずのメモリを読めてしまうかもしれないのです。
261
+
262
+ <!-- This is why Rust forbids using `v` after we’ve done the move. -->
263
+ このような理由から、Rustはムーブを終えた後の ` v ` の使用を禁止するのです。
181
264
182
265
[ sh ] : the-stack-and-the-heap.html
183
266
184
267
<!-- It’s also important to note that optimizations may remove the actual copy of -->
185
268
<!-- the bytes on the stack, depending on circumstances. So it may not be as -->
186
269
<!-- inefficient as it initially seems. -->
187
- 最適化が状況によってはスタック上のバイトの実際のコピーを削除するかもしれないことに気付くことも重要です 。
188
- そのため、それは最初に思ったほど非効率ではないかもしれません 。
270
+ また知っておいてほしいのは、状況によっては最適化により、スタック上のバイトを実際にコピーする処理が省かれる可能性があることです 。
271
+ そのため、ムーブは最初に思ったほど非効率ではないかもしれません 。
189
272
190
273
<!-- ## `Copy` types -->
191
274
## ` Copy ` 型
@@ -197,7 +280,7 @@ let v2 = v;
197
280
<!-- behavior. For example: -->
198
281
所有権が他の束縛に転送されるとき、元の束縛を使うことができないということを証明しました。
199
282
しかし、この挙動を変更する [ トレイト] [ traits ] があります。それは ` Copy ` と呼ばれます。
200
- トレイトについてはまだ議論していませんが、とりあえずそれらを挙動を追加するある型への注釈として考えることができます 。
283
+ トレイトについてはまだ議論していませんが、とりあえずそれらを、ある型に対してある挙動を追加するための、注釈のようなものとして考えて構いません 。
201
284
例えばこうです。
202
285
203
286
``` rust
@@ -213,8 +296,8 @@ println!("v is: {}", v);
213
296
<!-- But, unlike a move, we can still use `v` afterward. This is because an `i32` -->
214
297
<!-- has no pointers to data somewhere else, copying it is a full copy. -->
215
298
この場合、 ` v ` は ` i32 ` で、それは ` Copy ` トレイトを実装します。
216
- これはちょうどムーブと同じように、 ` v ` を ` v2 ` に割り当てるとき、データのコピーが作られるということを意味します 。
217
- しかし、ムーブと違って後でまだ ` v ` を使うことができます。
299
+ これはちょうどムーブと同じように、 ` v ` を ` v2 ` に代入するとき、データのコピーが作られることを意味します 。
300
+ しかし、ムーブと違って、後でまだ ` v ` を使うことができます。
218
301
これは ` i32 ` がどこか別の場所へのポインタを持たず、コピーが完全コピーだからです。
219
302
220
303
<!-- All primitive types implement the `Copy` trait and their ownership is -->
@@ -285,7 +368,7 @@ fn foo(v: Vec<i32>) -> Vec<i32> {
285
368
286
369
<!-- This would get very tedious. It gets worse the more things we want to take ownership of: -->
287
370
これは非常に退屈になるでしょう。
288
- もっとたくさんのものの所有権を受け取れば、それはもっとひどくなります 。
371
+ もっとたくさんのものの所有権を受け取ろうとすると、状況はさらに悪化します 。
289
372
290
373
``` rust
291
374
fn foo (v1 : Vec <i32 >, v2 : Vec <i32 >) -> (Vec <i32 >, Vec <i32 >, i32 ) {
@@ -305,10 +388,10 @@ let (v1, v2, answer) = foo(v1, v2);
305
388
306
389
<!-- Ugh! The return type, return line, and calling the function gets way more -->
307
390
<!-- complicated. -->
308
- うわあ!
391
+ うわあ!
309
392
戻り値の型、リターン行、関数呼出しがもっと複雑になります。
310
393
311
394
<!-- Luckily, Rust offers a feature, borrowing, which helps us solve this problem. -->
312
395
<!-- It’s the topic of the next section! -->
313
396
幸運なことに、Rustは借用という機能を提供します。それはこの問題を解決するために手助けしてくれます。
314
- それが次のセクションの話題です!
397
+ それが次のセクションの話題です。
0 commit comments