2016-08-30 5 views
1

あなたは配列内の要素のインデックスを取得するためのオフセットポインタを使用することができますCでは、例えば:ポインタ算術を使用してベクトルの要素のインデックスを取得する方法は?

配列の要素への参照を考える
index = element_pointer - &vector[0]; 

、これはあまりにも錆に可能なはずです。

ベクトル要素からメモリアドレスを取得する能力がありますが、usizeに変換してから、それらを減算します.Rustでこれを行うにはもっと便利で便利ですか?

+0

これは、[[&str'の間のバイトオフセットを取得する方法](https://stackoverflow.com/questions/38268529/how-to-get-the-byte-offset-between-str) *答えは "単に' usize'に変換されました。 – mcarton

答えて

1

だから、人々がポインタやものを持ってきた問題を考えると、これを行うための私見最善の方法は、次のとおりです。

fn index_of_unchecked<T>(slice: &[T], item: &T) -> usize { 
    if ::std::mem::size_of::<T>() == 0 { 
     return 0; // do what you will with this case 
    } 
    (item as *const _ as usize - slice.as_ptr() as usize) 
    /std::mem::size_of::<T>() 
} 

// note: for zero sized types here, you 
// return Some(0) if item as *const T == slice.as_ptr() 
// and None otherwise 
fn index_of<T>(slice: &[T], item: &T) -> Option<usize> { 
    let ptr = item as *const T; 
    if 
     slice.as_ptr() < ptr && 
     slice.as_ptr().offset(slice.len()) > ptr 
    { 
     Some(index_of_unchecked(slice, item)) 
    } else { 
     None 
    } 
} 

あなたが方法たい場合は、にもかかわらず:

trait IndexOfExt<T> { 
    fn index_of_unchecked(&self, item: &T) -> usize; 
    fn index_of(&self, item: &T) -> Option<usize>; 
} 

impl<T> IndexOfExt<T> for [T] { 
    fn index_of_unchecked(&self, item: &T) -> usize { 
     // ... 
    } 
    fn index_of(&self, item: &T) -> Option<usize> { 
     // ... 
    } 
} 

、その後、あなたはDeref sがすること、あらゆるタイプのため、この方法を使用することができますが[T]

+0

私は一般に 'index_of_unchecked'に' debug_assert'をお勧めします。 – ubsan

4

もっと簡単な方法はありません。その理由は、その答えを与える操作やメソッドが、Vec(またはより可能性の高いスライス)とそのコレクション内の何かでのみ使用できることを保証することは難しいと思います。 Rustはあなたが別のベクトルへの参照でそれを呼び出すことを許可したくありません。

もっと慣用的なことは、まず最初に行う必要がないことです。あなたはVecに参照を保存することはできません。なぜなら、とにかく寿命のためにVecから離れたところに非常に永遠にあるので、もしあなたがリファレンスを持っていればインデックスを手に入れることができます。

特に、反復する場合は、enumerateを使用して、(index, &item)のペアを反復処理します。

+0

一般的なケースではEnumerateは問題ありませんが、関数が(特別な場合には)親を取得してからベクトルから参照を削除する必要があることもあります。インデックスを通すことは可能ですが、不便です。 – ideasman42

関連する問題