2016-12-16 11 views
1

に変換する安全な方法は何ですか?メモリ内で移動することなく、ベクトルのヒープ割り当てに生涯を割り当てる方法を教えてください。Vec <T>を&[T]

私はこれを行うために見つけた最も簡単な方法は、

pub fn heap_slice<'a, T:'a>(x: Vec<T>) -> &'a [T] { 
    use std::mem::forget; 
    use std::slice::from_raw_parts; 
    x.shrink_to_fit(); 
    let ptr = x.ptr(); 
    let len = x.len(); 
    forget(x); 
    unsafe{ from_raw_parts(ptr,len) }; 
} 

である。しかし、これは一般的に眉をひそめるさSTDLIBのunsafe外を呼び出しません。安全な方法はありますか?

私はinto_boxed_sliceとほぼ同じことをしています。しかし、&[T]を復旧し、一旦それがBox<[T]>になると寿命を割り当てるにはどうすればよいですか?

答えて

6

スライス(&'a [T])は、別のオブジェクトが所有する一部の配列(たとえば、Vec<T>またはBox<[T]>)のビューを表すはずです。そのため、リファレンスには生涯パラメータがあり、Vec<T>Box<[T]>は参照できません。

スライスが「ドロップ」されている場合、スライスにはメモリがないため、メモリは解放されません。したがって、関数によってベクトルの記憶域がリークします。スライスに生涯を "魔法のように割り当てる"ことはできず、ヒープ割り当てを解放するコードをコンパイラに挿入させることはできません。スライスをコピーするとどうなりますか?

Rustは、スライスが必要なコンテキスト(ジェネリックが含まれている場合を除いて)で自動的にベクタまたはボックススライスをスライスに強制しますので、実際にはルールに反してスライスを返す理由はありませんベクトルまたはボックス化されたスライスを返します。

おそらくライブラリを作成していて、ベクターを返すと実装の詳細がわかるのではないかと心配していますか?あなたがCでライブラリを書くのであれば、生ポインタを使うでしょうが、呼び出し側が何らかの関数を呼び出すことになっているかどうか(そしてどちらを呼び出すべきか)APIドキュメントを書く必要があります。リソースをアップするかどうか。 Rustでは、適切な戻り値の型を使用してこれらの命令をエンコードするので、プログラマはそれを心配する必要はありません。

少なくともBox<[T]>を借りる方法のコード例はありますか? as_ref()またはborrow()は(xBox<[T]>です)Box<[T]>から借りる最短の方法は&xまたは&*xを書くことで人生の時間の割り当て

ことはできません。 &xBoxDeref特性を実装しているため、タイプ&Box<[T]>の値を生成します。これは&[T]に強制変更できます。

有効な有効期間パラメータを持つスライスを関数から返すには、関数の入力パラメータの1つの有効期間パラメータにリンクする必要があります。 Boxが関数の最後までに削除されることを期待しているので(つまり、mem::forgetを呼び出すことでこれを防ぐことができますが、コンパイラは理由を記述することができません)、関数に値でBox<[T]>を渡すと、リンクすることはできませんそのことについて)。 Box<[T]>を参照(例:&Box<[T]>)に渡すことはできますが、不要なインダイレクションレイヤが導入されるだけで、代わりに&[T]を受け入れる必要があります。

+0

おかげで基本的に私はスライスをラップし、ドロップ特性を追加する必要があります!(私はTLSメッセージパケットを一緒に使用していて、一度結合したカップルKBになるようにしようとしています。簡単にスライスして内容を簡単に借りることができるので、スライスを再割り当てしたくないです。 – Valarauca

+0

少なくとも、Box <[T]> 'を借りる方法のコード例を提供できますか? 'as_ref()'または 'borrow()'はファイルの時間割り当てを許可しません – Valarauca

関連する問題