✅
どっちを使う?Rustの&strとStringの違いを図解で学ぼう
Rustの文字列型には &str と String の2種類が存在します。
「どっちを使えばいいの?」「どう違うの?」と悩んだことはありませんか?
この記事では、所有権・可変性・メモリ構造などの観点から、両者の違いをわかりやすく解説します。
&strとは?
&strは「文字列スライス」と呼ばれ、自分では文字列の実体を持たず、メモリ上の他の場所にある文字列データを参照するだけの軽量な型です。
let greeting: &str = "hello";
この場合、"hello"という文字列はプログラムのバイナリ(静的領域)に埋め込まれており、&strはそれをポインタと長さで参照しています。
- 所有権を持たない
- 不変(immutable)
- 軽量
- よく関数の引数などに使われる
Stringとは?
Stringはヒープ上に確保された文字列の所有者です。可変で、長さを変更したり、新しい文字列を構築したりできます。
let mut name: String = String::from("Alice");
name.push_str(" Smith");
- 所有権を持つ
- 可変(mutable)
- ヒープ上にデータを持つ
-
to_string()で簡単に作れる
メモリ構造の違い
Rustでは、スタックとヒープという2つのメモリ領域を使い分けています。それぞれの型がどのようにこれらを使っているかが、&strとStringの違いの鍵になります。
&str のメモリ構造:参照型(スライス)
let s: &str = "hello";
何が起こっているか
-
"hello"はコンパイル時に静的メモリ領域に埋め込まれます(.rodataセクションなど)。 -
sはスタック上に作られる ポインタと長さ(slice構造) です。 -
s自身は軽量で、文字列の所有権を持ちません。
図解

特徴まとめ
| 項目 | 説明 |
|---|---|
| 所有権 | なし(借用) |
| メモリ場所 | 参照先に依存(リテラルなら静的メモリ) |
| サイズ変更 | 不可(長さは固定) |
| 開放タイミング | 所有者に従う(&str自身は所有者でない) |
String のメモリ構造:所有型(ヒープ確保)
let s: String = String::from("hello");
何が起こっているか
-
"hello"というデータはヒープに動的確保されます。 -
sはスタック上に、以下の3つの情報を持ちます。- ポインタ(ヒープ上の先頭アドレス)
- 長さ(len)(文字数、バイト単位)
- 容量(capacity)(確保されたバイト数)
図解

特徴まとめ
| 項目 | 説明 |
|---|---|
| 所有権 | あり(Dropで自動解放) |
| メモリ場所 | 実体はヒープ、管理情報はスタック |
| サイズ変更 | 可能(容量の範囲内なら追加コストなし) |
| 解放タイミング | スコープを抜けたときに自動で Drop
|
相互変換
&str → String
let s: &str = "hello";
let owned: String = s.to_string();
String → &str
let s: String = String::from("hello");
let slice: &str = &s;
使用例
fn greet(name: &str) {
println!("Hello, {name}!");
}
fn main() {
let s1 = "world"; // &'static str
let s2 = String::from("Rustacean"); // String
greet(s1); // OK
greet(&s2); // OK: &String は自動で &str に変換される
}
比較まとめ
| 特徴 | &str |
String |
|---|---|---|
| 所有権 | なし | あり |
| 可変性 | 不変 | 可変 |
| メモリ位置 | 静的 or 他のヒープ | 自前のヒープ |
| サイズ変更 | 不可 | 可 |
| コピーコスト | 軽量 | 重い(Clone or ムーブ) |
おわりに
Rustでは「所有権」や「借用」という概念が重要で、&strとStringはその代表例です。
どちらを使うかは用途によって変わりますが、基本は次のように覚えておけばOKです。
- 変更しない & 借用するなら
&str - 所有して操作したいなら
String
Discussion