- GCは失敗。メモリは自分で管理せよ! その2©2ch.net
253 :デフォルトの名無しさん[sage]:2015/12/08(火) 19:22:21.31 ID:RKxPG6yJ - Rustはどう?
明文化されたmoveセマンティクスと、オブジェクトの寿命と参照のチェッカを型システムに組み込んでるおかげで、 リソース管理の実行時コストをゼロにしつつ、メモリリークが発生しないプログラムが書ける。 shared_ptrに相当するRcもあるから、所有者を複数にしたい場合のコストもそれなりに抑えられる。
|
- GCは失敗。メモリは自分で管理せよ! その2©2ch.net
256 :デフォルトの名無しさん[sage]:2015/12/08(火) 21:00:06.21 ID:RKxPG6yJ - >>254 難しいのは難しいが、低レベルの世界に相応な難易度であって、理不尽さはあまり無いと思う。
自分が遭遇した理不尽というか不便は、トレイト(型クラスみたいなの)を戻り値にした、ジェネリックな関数の型注釈の煩雑さで、 そのworkaroundが、その関数の返り値専用の型を定義する、ってのがカルチャーショックだった。 https://doc.rust-lang.org/std/iter/trait.Iterator.html ↑はIteratorトレイト(Listインターフェイスみたいなもの)のドキュメントだけど、mapとかfoldとかよくある高階関数の戻り値が、それ専用の型(MapとかFold)になってる。 だから、よくある関数型言語のイメージで、何か高階関数を利用したアダプタ関数を試しに定義してみよう!ってやると、 型注釈のエラー、ライフタイムのエラー等が一辺に出てきてわけが分からなくなる。 その関数の戻り値専用の型、なんて贅沢に見えるけど、返り値のサイズを見る限り、余計なデータで膨れているわけでもなかった。 Cでstruct wrap_int { int c; };とやったときにsizeof(wrap_int)がsizeof(int)と等しいけど、それと同じことをやっていた。 型情報なんてコンパイル時に全部消えちゃうから、実行コストも無いんじゃないかと今では思う。 メモリ/リソースの所有権を意識してコードを書くこと、が身について面白いよ。 ヒープを贅沢に使ってコピーしまくりなコードを書くと汚いし遅いしなんで、ちょっとダイエットする気分も出てくる。
|
- GCは失敗。メモリは自分で管理せよ! その2©2ch.net
258 :デフォルトの名無しさん[sage]:2015/12/08(火) 22:59:22.32 ID:RKxPG6yJ - >>255 shared_ptrと恒等なものは無いけど、ポインタ的に使える型がBox, Rc, Cell(あるいはRefCell)とあって、
Boxはヒープ領域であること、Rcは複数の所有者がいる(つまり所有者全員が死ぬまでは生きている)こと、Cellは複数の書き込みが作れること、 とか機能とコストが別れているから、これらを組み合わせて使う。 で、Thread Safetyを実現させる機構は上記には無いので、Atomicityを導入させるRcの類似形であるArcと、 書き込みもしたいならMutexっていう型も合わせて使う。 すると、例えば整数のベクトルをスレッド間で共有したい、とかになるとArc<Mutex<Vec<i32>>>という目が滑るような型表記をすることになる。 あんま詳しくないので、ケース毎にもっと簡単なやり方があるとは思うんだけどね。
|