web-dev-qa-db-ja.com

スライスと配列の違いは何ですか?

この例で&[u8]&[u8; 3]の両方が問題ないのはなぜですか?

fn main() {
    let x: &[u8] = &[1u8, 2, 3];
    println!("{:?}", x);

    let y: &[u8; 3] = &[1u8, 2, 3];
    println!("{:?}", y);
}

&[T; n]&[T]に強制できるという事実は、それらを許容できるようにする側面です。 —クリス・モーガン

&[T; n]&[T]に強制できるのはなぜですか?この強制は他にどのような状況で起こりますか?

27
runrioter

_&[T; n]_が_&[T]_に強制できるのはなぜですか?

もう1つの答えは、_&[T; n]_shouldが_&[T]_に強制変換される理由を説明しています。ここでは、コンパイラがその_&[T; n]_canは_&[T]_に強制変換します。

Rustで可能な4つの強制

  1. 推移性。

    • TUに強制変換し、UVに強制変換する場合、TVに強制変換します。
  2. ポインターの弱体化:

    • 可変性の削除:_&mut T_→_&T_および_*mut T_→_*const T_
    • 生のポインタへの変換:_&mut T_→_*mut T_および_&T_→_*const T_
  3. Deref trait

    • _T: Deref<Target = U>_の場合、_&T_はderef()メソッドを介して_&U_に強制変換します
    • (同様に、_T: DerefMut_の場合、_&mut T_はderef_mut()を介して_&mut U_に強制変換されます)
  4. Unsize trait

    • Ptrが「ポインタ型」(例:_&T_、_*mut T_、BoxRcなど)、および_T: Unsize<U>_の場合、次に、_Ptr<T>_は_Ptr<U>_に強制変換します。

    • Unsizeトレイトは、次の場合に自動的に実装されます。

      • _[T; n]: Unsize<[T]>_
      • _T: Unsize<Trait>_ここで_T: Trait_
      • _struct Foo<…> { …, field: T }: Unsize< struct Foo<…> { …, field: U }>_、ただし_T: Unsize<U>_(およびコンパイラーのジョブを容易にするためのいくつかの条件)
    • (Rustは、_Ptr<X>_を実装する場合、「ポインタ型」として認識します CoerceUnsized 。実際のルールは、「if _T: CoerceUnsized<U>_次にTU "に強制変換します。)

_&[T; n]_が_&[T]_に強制変換される理由は、ルール4です。(a)コンパイラーはすべての_impl Unsize<[T]> for [T; n]_に対して実装_[T; n]_を生成し、(b)参照_&X_ポインタ型です。これらを使用して、_&[T; n]_canは_&[T]_に強制変換できます。

11
kennytm

enter image description here

@ShepmasterとChrisMorganの回答に従って、さまざまな概念を説明するメモ画像を貼り付けます。

0
keroro520