iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 14
0

各位好,時間過得有點快沒想到已經 Day14 了!/images/emoticon/emoticon04.gif,不知道時間夠不夠達成我當初設定的目標呢?
那麼今天就繼續把 ownership 的概念完成吧!今天要講的是 ownership 在函式裡面的轉移方式,Let'go!

Ownership and Functions

傳遞值給函式(function)時其實跟我們把值 assign 給變數時是類似的方式,也就是說當把值傳給函式時同樣會用 move 或是 copy 的方法處理,那麼我們就直接看個例子,

fn ownership_and_functions() {
  let s = String::from("hello"); // s 現在在 scope 裡面

  takes_ownership(s); // 由於 s 是用 heap 法處理所以 move
                      // 因此 s 的所有權已經被轉移了

  println!("s = {}", s); // 這時已經取得不了 s 編譯會報錯
                     ^ value borrowed here after move

  let x = 5; // 反之如果是 stack 法處理

  makes_copy(x); // x 就會 copy 一份後進到函式裡面
                 // 所以還是可以印得出 x 不會報錯
  println!("x = {}", x);
}
  
fn takes_ownership(some_string: String) {
  println!("{}", some_string);
}

fn makes_copy(some_integer: i32) {
  println!("{}", some_integer);
}

如果我們試著取得 s 在他 move 所有權之後編譯器就會報錯反之如果是用 copy 的方式處理的就不會。

Return Values and Scope

而同樣當函式返回值的時候也會轉移所有權,例如下面的例子,

fn ownership_and_return_values() {
  let s1 = gives_ownership(); // s1 的所有權是從 gives_ownership 來的
                              // 其值為 "hello"

  let s2 = String::from("hello"); // 宣告一個新的變數 s2

  let s3 = takes_and_gives_back(s2); // s2 move 進 takes_and_gives_back
                                     // takes_and_gives_back, 同時也返回所有權
                                     // 現在 s3 有所有權
                                     
  println!("{}", s2); // 報錯因為 s2 的所有權已經轉移給 s3
  println!("{}", s3); // 不會報錯 s3 擁有所有權
}

fn gives_ownership() -> String {
  // gives_ownership 這支程式將會把 some_string 的擁有權
  // 傳出去給呼叫他的另外一個擁有者

  let some_string = String::from("hello"); // 宣告一個新的變數 some_string

  some_string // 返回 some_string
              // move 出去給呼叫他的擁有者
}

// 直接返回傳入的值
fn takes_and_gives_back(a_string: String) -> String {
  a_string
}

也就是說 ownership (所有權)會在函式之中被傳來傳去,但是同時也造成麻煩例如,

fn main() {
    let s1 = String::from("hello");

    let (s2, len) = calculate_length(s1);

    println!("The length of '{}' is {}.", s2, len);
}

// 如果我們還需要使用 s 時必須再把他回傳
fn calculate_length(s: String) -> (String, usize) {
  let length = s.len(); // 算出 String 的長度

  (s, length)
}

這樣的方式太攏長會造成寫程式時的不便,因此接下來會介紹 Rust reference 的概念。

總結

今天介紹了 ownership 如何在函式裡面傳遞但是同時也造成了一些麻煩,所以下一篇我們會來介紹怎麼比較好的處理這樣的情況也就是 References and Borrowing 的概念。

那麼我們明天見!

最後一樣有問題歡迎發問

/images/emoticon/emoticon07.gif


上一篇
[Day 13] Rust Ownership 所有權 (2)
下一篇
[Day 15] Rust References and Borrowing 參照與借用
系列文
WebAssembly + Rust 的前端應用30

尚未有邦友留言

立即登入留言