Cow 型 (clone-on-write の略) について。

概要

以下の特徴を持つスマートポインタ。

※ 参照方式で to_mut を呼ぶと、所有方式にするために参照先がクローンされる。

よくある用法

既定値なら参照で共有し、カスタム値に変化した場合にだけ所有にする。

既定値が多い場合、この方法はクローン時間とメモリの大幅な節約になる。

サンプル 1

動作の確認

以下では、参照と所有それぞれの形態で読込と書込を行っている。


use std::borrow::Cow;

fn main() {
    let mut cow1 = Cow::<i32>::Borrowed(&42);
    let mut cow2 = Cow::<i32>::Owned(42);

    assert_eq!(*cow1, 42);
    assert_eq!(*cow2, 42);

    *Cow::to_mut(&mut cow1) += 1;
    *Cow::to_mut(&mut cow2) += 1;

    assert_eq!(*cow1, 43);
    assert_eq!(*cow2, 43);
}

サンプル 2

よくある用法

以下では、text0text1 は既定値を共有して参照している。
そして、text2text3 はそれぞれ独自の値を所有している。


use std::borrow::Cow;

fn main() {
    let text0 = &mut TextHolder::new();
    let text1 = &mut TextHolder::new();
    let text2 = &mut TextHolder::new();
    let text3 = &mut TextHolder::new();

    text2.add_em();
    text3.set_custom("Custom text");

    assert_eq!(text0.get(), "Default text");
    assert_eq!(text1.get(), "Default text");
    assert_eq!(text2.get(), "Default text!");
    assert_eq!(text3.get(), "Custom text");
}

struct TextHolder(Cow<'static, str>);

impl TextHolder {
    fn new() -> Self {
        static TEXT: &str = "Default text";
        Self(Cow::Borrowed(TEXT))
    }

    fn get(&self) -> &str {
        &*self.0
    }

    fn add_em(&mut self) {
        Cow::to_mut(&mut self.0).push_str("!");
    }

    fn set_custom(&mut self, value: &str) {
        self.0 = Cow::Owned(value.to_string());
    }
}