Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Rust辞典

  1. トップページ
  2. Rust辞典
  3. Rc<T> / Arc<T>

Rc<T> / Arc<T>

『Rc<T>』と『Arc<T>』は参照カウント方式のスマートポインタで、1つの値を複数の場所から所有できるようにします。『Rc』はシングルスレッド用、『Arc』はマルチスレッド対応版です。

構文
use std::rc::Rc;
use std::sync::Arc;

// Rc:シングルスレッドで複数の所有者を作ります。
let a = Rc::new(値);
let b = Rc::clone(&a); // 参照カウントが増えます。

// Arc:マルチスレッドで複数の所有者を作ります。
let a = Arc::new(値);
let b = Arc::clone(&a); // スレッドをまたいで共有できます。

// 参照カウントの確認
Rc::strong_count(&a)
Arc::strong_count(&a)
メソッド一覧
メソッド概要
Rc::new(v)値vをRcでラップします。参照カウントは1になります。
Rc::clone(&a)参照カウントを増やしながら新しいRcポインタを作ります。
Rc::strong_count(&a)現在の強参照カウントを返します。
Rc::weak_count(&a)現在の弱参照カウントを返します(Weak参照用)。
Arc::new(v)値vをArcでラップします。スレッドをまたいで安全に共有できます。
Arc::clone(&a)参照カウントをアトミックに増やしながら新しいArcポインタを作ります。
サンプルコード
use std::rc::Rc;
use std::sync::Arc;
use std::thread;

fn main() {
    // Rc:シングルスレッドで複数所有します。
    let rc_val = Rc::new(String::from("shared"));
    let rc_a = Rc::clone(&rc_val);
    let rc_b = Rc::clone(&rc_val);

    println!("{}", rc_val); // shared
    println!("{}", rc_a);   // shared
    println!("count: {}", Rc::strong_count(&rc_val)); // count: 3

    drop(rc_a);
    println!("after drop: {}", Rc::strong_count(&rc_val)); // after drop: 2

    // Arc:スレッド間で共有します。
    let arc_val = Arc::new(42);
    let handles: Vec<_> = (0..3).map(|i| {
        let val = Arc::clone(&arc_val);
        thread::spawn(move || {
            println!("thread {}: {}", i, val);
        })
    }).collect();

    for h in handles {
        h.join().unwrap();
    }
}
実行結果
shared
shared
count: 3
after drop: 2
thread 0: 42
thread 1: 42
thread 2: 42
概要

Rustの所有権システムでは通常1つの値に所有者は1人だけですが、『Rc<T>』や『Arc<T>』を使うと複数の所有者を持つことができます。すべての参照がなくなったとき(カウントが0になったとき)にメモリが自動的に解放されます。

『Rc』はスレッド間で共有できません(『Send』トレイトを実装していないため)。スレッド間共有には必ず『Arc』を使用してください。

Rcを使った循環参照はメモリリークを引き起こします。循環参照を作る可能性がある場合は、片方を『Weak<T>』(弱参照)にしてカウントが循環しないようにする必要があります。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。