String and &str in rustについて

github.com

Twitterでみかけたこちら。

string memory layout pdf cite

pdfから一部切り取って抜粋

String is a Vec

本当にそうだろうか。
RustのStringの実装を見てみると、

pub struct String {
    vec: Vec<u8>,
}

https://github.com/rust-lang/rust/blob/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/liballoc/string.rs#L283-L285

String is a Vecは正しそうです。

    pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
        String { vec: bytes }
    }

rust/string.rs at master · rust-lang/rust · GitHub

String::from_utf8_uncheckedという、VecからStringを生成するunsafeなメソッドの実装を見ると、単にVecを移植しているだけなのでよさそうです。

fn main() {
    let text: String = "abcde".to_string();
    let vector = unsafe { std::mem::transmute::<String, Vec<u8>>(text) };
    println!("{:?}", vector); // => [97, 98, 99, 100, 101]
    let text: String = unsafe { std::mem::transmute::<Vec<u8>, String>(vector) };
    println!("{}", text); // => abcde
}

Rust Playground

transmuteで相互に変換することもできました。

では、この図は正しいでしょうか

string memory layout pdf cite

fn main() {
    println!("{}", std::mem::size_of::<String>()); // => 24
    println!("{}", std::mem::size_of::<Vec<u8>>()); // => 24
}

Rust Playground

StringもVecもSizedなので、std::mem::size_ofできます.

上の図だと文字列の長さによってメモリ上のサイズが増えそうですが、StringもVecも24byteと固定長のようです

cipepser.hatenablog.com

こちらの記事にVecとSliceのメモリレイアウトについて書かれていますが、
上記の図はいかにもslice的ですね。

Vecはusize3つ(正確には*const u8とusizeとusize)しか持たないので、64bit * 3で24 byteです

なので String and &str in rustを鵜呑みにするとより混乱してしまうかも・・・と思いました。