DSTは単独で扱えない
GPT-4.icon
[T] や str が単独で使えない理由
Rustでは、コンパイル時にサイズが確定しない型は「ダイナミックサイズ型(DST: Dynamically Sized Type)」と呼ばれます。このような型(例えば [T] や str)は、スタック上で単独の値として扱うことができません。その理由を詳しく説明します。
---
1. スタックとサイズの関係
Rustでは、スタックフレームにデータを配置する際に、そのデータのサイズがコンパイル時に完全に分かっている必要があります。これは以下の理由によります:
1. 効率性:
スタックは高速で固定長のメモリ領域であるため、データのサイズが決まっていれば、スタック上で効率的にメモリ操作が可能です。
2. 型安全性:
Rustはコンパイル時に型とメモリサイズの一貫性を確認します。サイズが動的であると、型安全性が保証できなくなります。
2. [T] や str がサイズ不定である理由
[T] の場合
[T]は要素数が不明であるため、コンパイル時にデータ全体のサイズが確定しません。
例えば、[i32]という型では「i32の配列」であることは分かりますが、「何個の要素が含まれているか」は情報として欠けています。
str の場合
strはUTF-8エンコーディングの文字列型ですが、文字列の長さ(バイト数)は動的に変わるため、str型そのものもサイズが不定です。
---
3. サイズ不定型(DST)をスタック上で扱えない理由
Rustでは、サイズ不定型(DST)は単独で値として存在できないという制約があります。その理由は以下の通りです:
1. サイズが不定の型は、メモリ領域を確保できない
例えば、[i32]型をスタック上で直接扱おうとすると、「要素数が不明」のため、どれだけのメモリを確保するべきか分かりません。
2. 参照やポインタでサイズを補完する必要がある
&[i32]のような参照では、以下の情報がセットで保持されます:
データの開始位置(ポインタ)
要素数(長さ)
これにより、データのサイズが不定でも、間接的にその内容を扱うことが可能になります。
わかりやし〜〜mrsekut.icon*2
---
5. &[T] や Box<[T]> の仕組み
スライス([T])を扱う場合、以下のような間接的な形で使われます:
1. &[T](参照型)
&[T]はメモリ上に以下の情報を持っています:
データの開始位置(ポインタ)
長さ(usize型)
この情報を用いて、データがどこから始まり、何個の要素が含まれているかを把握します。
2. Box<[T]>(スマートポインタ型)
Box<[T]>は[T]をヒープ上に確保し、そのポインタを保持します。
ヒープ領域では、動的なサイズのデータを扱えるため、[T]をヒープに置くことで動的配列のように利用可能になります。
7. 具体例で理解する
配列とスライスの違い
code:rust
fn main() {
let slice: &i32 = &array; // スライス (動的長、参照) println!("{:?}", slice); // 1, 2, 3 }
この場合、arrayはスタック上に直接存在します。一方、sliceはarrayの参照と長さを持つ構造体のようなものです。