10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rustのstd::rc::Rcってなんなのさ

Last updated at Posted at 2020-04-03

はじめに

今日もRustのコードを読んでいたら,

struct MediaChannel {
    ...
    metadata: Option<Rc<StreamMetadata>>,
    ...
}

Rc<T>みたいなやつが出てきて,役割とか使い方とか色々とわからなかったので調べてみました。

Rc<T>とは

プログラミング言語Rust」によると,

Rc は参照カウンタを持つポインタです。 言い換えると、これを使えば、あるデータを「所有する」複数のポインタを持つことができるようになるということです。そして、全てのポインタがスコープから外れたとき、そのデータは削除されます(デストラクタが実行されます)。

と書いてあります。

どういうことなのか説明

プログラミングRust」も参考にしていますが,

所有権

まず前提として,Rustのほとんどの値は唯一の所有者を持ちます。
Rustではこの所有権システムによってメモリ管理をしています。

Rustで値がメモリに保管されるとき,その値は変数に格納されています。
そして,その変数のことを値の所有者とみなします。
Rustにはスコープの概念があり,変数がそのスコープから外れたとき,その変数は所有権を失って自分の所有している値をメモリから開放します。

しかし,この「値一つに対して所有者が一つ」のシステムだけでは不便なときがあります。
例えば,値Aを使っているすべてのものが使い終わるまで値Aには生存しててほしいタイミングなどです。

こういうときに役立つのがRc<T>です。

参照カウンタ

RcはReference Counterの略で,参照カウンタとも呼ばれます。
ひとつコードを例にあげます。

use std::rc::Rc;

fn main() {
    let s: Rc<String> = Rc::new("Live".to_string());
    let t = s.clone();
    let u = s.clone();
}

最初の変数sには,ヒープに保存されているStringに対する参照が格納されています。
その後の行では,変数sをクローンしてそれぞれ変数tuを作っています。
stuはそれぞれスタックに保管されており,いずれもヒープに保存されているStringを参照しています。
ちなみにそのStringは,また別の場所にある"Live"という文字列型のデータを参照しています。

さて,ためしにRcポインタに所有される文字列の最後に何らかのテキストを追加してみます。

use std::rc::Rc;

fn main() {
    let s: Rc<String> = Rc::new("Live".to_string());
    let t = s.clone();
    let u = s.clone();
    
    s.push_str(" forever")
}

しかし,このコードに対してRustのコンパイラはエラーを吐いてしまいます。
※Rust Playground調べ

error[E0596]: cannot borrow data in an `Rc` as mutable
 --> src/main.rs:8:5
  |
8 |     s.push_str(" forever")
  |     ^ cannot borrow as mutable
  |
  = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<std::string::String>`

Rustは,Rcポインタから参照されているものは共有されるものと判断するので,不変であるべきだと判断するみたいです。

このstd::rc::Rcは他の言語にも出てくる参照カウンタと同じような感じみたいです。

まとめ

std::rc::Rcを使うと所有権システムとは違った変数の生存期間を作ってあげることができます。
それは,複数の変数で所有権を共有することで成り立たせることができます。
また,共有された値はコンパイラによって不変と判断されます。

なかなかドキュメントを読んだだけだと実際に上手に使えない所有権システムたちですが,がんばって理解していこうと思います。

参考リンク

https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/choosing-your-guarantees.html
https://doc.rust-lang.org/std/rc/struct.Rc.html
https://qiita.com/ksato9700/items/312be99d8264b553b193

参考文献

https://www.oreilly.co.jp/books/9784873118550/

10
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?