web-dev-qa-db-ja.com

オブジェクトを変更するが、オブジェクトを削除する可能性があるRustメソッドの署名?

私はRustで、基本的にデータをさまざまな方法で変換するステップのパイプラインを介してデータをプッシュするプログラムを書いています。データはEntryで表され、私は設計していますパイプラインのステップのStep特性。

トレイトには、エントリを処理するメソッドが必要です。私の最初のデザインはこれでした:

fn process(&self, entry: &mut Entry) -> ()

後で、エントリをドロップできるようにするためのいくつかの手順が必要であることに気付きました。つまり、パイプラインを介してエントリをこれ以上処理しないように、何らかの方法で呼び出し元に通知します。私はこれについて2つの異なる署名を検討しています:

fn process(&self, entry: Entry) -> Option<Entry> //Returns None if object is dropped.
fn process(&self, entry: &mut Entry) -> bool  //Returns false if object is dropped.

どれが最も慣用的で最もきれいだと思いますか?最初のオプションのように所有権を譲渡することでパフォーマンスの低下はありますか? 3番目に良い選択肢はありますか?

1
Anders

Dropトレイトのdrop()メソッドは_&mut self_で宣言されていますが、実際にはそのメソッドを直接呼び出すことはできません。代わりに、オブジェクトの所有権を取得するstd::mem::drop()を使用する必要があります。

これは理にかなっています。値が削除されると、初期化された状態では存在しなくなります。後でそれにアクセスすることは事実上未定義の振る舞いですが、それはまさにRustの生涯システムが防ごうとしていることです。 Rustは、まだ所有されているオブジェクトをドロップしません。

これにより、fn process(entry: Entry) -> Option<Entry>が機能するonly宣言として残り、選択肢があれば最も安全なオプションにもなります。これは、明示的に削除する必要がないことを意味することに注意してください。Some(entry)の代わりにNoneを返すだけで、暗黙的にエントリが削除されます。

オブジェクトの所有権を移動すると、通常は浅いコピーが必要になるため(C++のmove-constructorやCのmemcpy()など)、パフォーマンスコストがわずかになる可能性があります。大きな構造体でない限り、これはほとんどのオブジェクトにとって問題ではありません。これが心配な場合は、代わりに_Box<Entry>_を使用してください。これにより、移動を回避するためにポインターの間接参照が追加されます。

5
amon