iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0

昨天提到了「borrow」的概念,今天要來更深入一點

除了借用出去,其實還可以做一點修改喔

沿用昨天的例子

fn main() {
    let shop1 = ["milk", "tea", "coffee"];
    let shop2 = &shop1;
}

為了慶祝盛大開幕, shop2 店希望能來個開幕限定商品,需要將 milk 與 tea 結合,變成 milk tea,不過原本的 milk 與 tea 還是會販售

在之前的文章提到,變數的值以後會改變的話,我們可以加上 mut

不過在借用的時候並不是在原本的值上面加上 mut 喔(好像有點難理解,直接下程式碼)

由於 Array 在宣告後就不能做變動,這邊我們就改成 Vec,並且加上 mut

fn main() {
    let mut shop1 = vec!["milk", "tea", "coffee"];
    let shop2 = &shop1;

    shop2.push("milk tea");
}

來看一下執行結果

這邊寫著 shop2 不可用可修改的方式借用

> cargo run

error[E0596]: cannot borrow `*shop2` as mutable, as it is behind a `&` reference
 --> src/main.rs:5:5
  |
5 |     shop2.push("milk tea");
  |     ^^^^^^^^^^^^^^^^^^^^^^ `shop2` is a `&` reference, so the data it refers to cannot be borrowed as mutable
  |
help: consider changing this to be a mutable reference
  |
3 |     let shop2 = &mut shop1;
  |                  +++

For more information about this error, try `rustc --explain E0596`.
warning: `hello_world` (bin "hello_world") generated 1 warning
error: could not compile `hello_world` (bin "hello_world") due to previous error; 1 warning emitted

由於能修改的權限本身還是在 shop1 上,

借出去的時候並沒有把修改權借給 shop2 ,

如果要讓 shop2 可修改,我們需要在 & 後面加上 mut

fn main() {
    let mut shop1 = vec!["milk", "tea", "coffee"];
    let shop2 = &mut shop1;

    shop2.push("milk tea");

    println!("shop2's sell {:?}", shop2)
}
> cargo run

shop2's sell ["milk", "tea", "coffee", "milk tea"]

但如果我們一次要借給很多店呢?

fn main() {
    let mut shop1 = vec!["milk", "tea", "coffee"];
    let shop2 = &mut shop1;
    let shop3 = &mut shop1;

    shop2.push("milk tea");
    shop3.push("coffee milk");

    println!("shop2's sell {:?}", shop2);
    println!("shop3's sell {:?}", shop3);
}

執行後會有這個訊息:不能同時以可修改的方式借出多次

> cargo run

error[E0499]: cannot borrow `shop1` as mutable more than once at a time
 --> src/main.rs:4:17
  |
3 |     let shop2 = &mut shop1;
  |                 ---------- first mutable borrow occurs here
4 |     let shop3 = &mut shop1;
  |                 ^^^^^^^^^^ second mutable borrow occurs here
5 |
6 |     shop2.push("milk tea");
  |     ---------------------- first borrow later used here

For more information about this error, try `rustc --explain E0499`.
error: could not compile `hello_world` (bin "hello_world") due to previous error

但如果以不修改的方式呢?

fn main() {
    let shop1 = vec!["milk", "tea", "coffee"];
    let shop2 = shop1;
    let shop3 = shop1;

    println!("shop2's sell {:?}", shop2);
    println!("shop3's sell {:?}", shop3);
}

單純的借用就可以借給多個變數囉

> cargo run

fn main() {
    let shop1 = vec!["milk", "tea", "coffee"];
    let shop2 = &shop1;
    let shop3 = &shop1;

    println!("shop2's sell {:?}", shop2);
    println!("shop3's sell {:?}", shop3);
}

上一篇
Day 16 - Ownership part 2
下一篇
Day 18 Ownership part 4
系列文
成為程式界的 F1 賽車手,用 30 天認識 Rust 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
hello world
iT邦新手 5 級 ‧ 2023-10-02 19:55:29

幫大大總結一下,rsut的借用規則

  • 在任何時候,我們要嘛只能有一個可變參考,要嘛可以有任意數量的不可變參考。
  • 參考必須永遠有效。

感謝大大補充 /images/emoticon/emoticon08.gif

我要留言

立即登入留言