急にRustやりたくなったのでちょっとやっている.のでメモ.
やったこと
標準入力から文字列を受け取って,トライ木を作成して表示するプログラムを作った(まだ途中)
気付き
- Rustにランタイムない(Cですよ~みたいな感じでLLVMに渡されてその最適化を受けているらしい)
- 文字列たくさんある
&str
とString
- 前者はリテラルなので変更不可能
- 後者は変更できるらしい
char[]
はないのか?
- structはまさにCスタイルのstructで,メモリにそのままの構造で(?)乗る
- LLやってると完全に無視しがち
- ローカル変数は全てスタックに乗る
Box<T>
というのを使うとヒープに載せられるようだ- だがその寿命は中に入れたもののスコープと同じでなければならない
- dangling pointerを防ぐため
- Lifetime specifierというよくわからない機構がある
- たぶん寿命を操作できる
- これ値を直接いじってるの?参照上の同一領域をいじってるの?みたいなのが時々分からなくなる
- 関数に
foo(some_struct)
みたいなのを渡したらどうなる?- C風に言えばポインタが渡る
- ついでに所有権も移る
Copy
トレイトが実装されていなければデフォで参照渡しになるっぽい
- 関数に
- 所有権移ったら使えないのは困るので
&
すると便利- Cのポインタの話はいったん忘れると良さそう
- 変更もさせたいときは
&mut
つける
まとめ
PerlやScalaやっているときはメモリレイアウトとか考える必要はほぼなくて,どっかにオブジェクトがあってそのうちGCされる,という世界観なので気楽. Rustではそうはいかなくて,速く(Rustには一般的な意味でのランタイムが存在しない)安全に動作させるためにメモリについて考えることを強制される,というイメージがある.
例えばstruct.Perlでは雑にHashRefを作ってポンポン何かを入れてるし,ScalaではCase Classを作成して雑に扱えるけど,Rustのstructは中に入れたものがそのままメモリに直接格納されるので,巨大なものをstructに入れたければBox<T>
みたいなものを使ってポインタにする必要がある.木構造を雑にstructで書くと,巨大な塊を占有することになって困るし,構造体のサイズは実行するまで不明になるのでコンパイルは通らないはず.
あと,困ったらrust vec memory layout
みたいにメモリレイアウトを検索すると便利そう.