やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustの所有権(スライス)

 部分配列の参照。元メモリと整合性がとれる。

成果物

参考

部分配列の問題

fn main() {
    let mut s = String::from("hello");
    let len = s.len();
    s.clear();
}

 s.clear()で文字列長は0になった。なのにlenは未だhelloだった頃の文字列長5を保持している。slenの整合性がとれていない状態となる。

文字列スライス

fn main() {
    let s = String::from("hello world");
    let hello = &s[0..5];       // &s[..5]
    let world = &s[6..11];      // &s[6..]  &s[6..len]
    let helloworld = &s[0..11]; // &s[..]
}

 &は参照。メモリ領域を変更せず読取る。[開始..終了]で全体から指定した部分だけを参照する。

部分文字列の整合性

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s); // error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
    s.clear();
    println!("{} {}", s, word);
}
fn first_word(s: &String) -> &str {
    let b = s.as_bytes();
    for (i, &item) in b.iter().enumerate() {
        if b' ' == item { return &s[..i]; }
    }
    &s[..]
}

 first_wordの引数sは不変である。(結果も不変を前提としている)。だが、s.clear()で変更されてしまった。変数swordの整合性がとれなくなる。だが、コンパイルエラーになってくれる。

 文字列スライスのほうを先にメモリ解放してしまえば問題ない。

fn main() {
    let mut s = String::from("hello world");
    {
        let word = first_word(&s); // OK
    }
    s.clear();
}

文字列リテラル=スライス

let s = "hello"; // &str型=不変な参照

String→&str

 first_word関数の引数を&str型にすると、String, &str両方の型で使える。

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);
    let word = first_word(&s[..]);
    println!("{} {}", s, word);
}
fn first_word(s: &str) -> &str {
    let b = s.as_bytes();
    for (i, &item) in b.iter().enumerate() {
        if b' ' == item { return &s[..i]; }
    }
    &s[..]
}

配列のスライス

let a = [1,2,3,4,5];
let slice = &a[1..3];

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで