參考和點運算子

我們學過當你有一個參考時,你要用 * 來取得值。參考是一種不同的型別,所以這是無法執行的:

fn main() {
    let my_number = 9;
    let reference = &my_number;

    println!("{}", my_number == reference); // ⚠️
}

編譯器印出:

error[E0277]: can't compare `{integer}` with `&{integer}`
 --> src\main.rs:5:30
  |
5 |     println!("{}", my_number == reference);
  |                              ^^ no implementation for `{integer} == &{integer}`

所以我們把第 5 行改成 println!("{}", my_number == *reference);,現在印出的是 true,因為現在是比較 i32 == i32,而不是比較 i32 == &i32。這就是所謂的反參考。

但是當你使用方法時,Rust 會為你反參考。方法中的 . 被稱為點運算子(dot operator),用來免費做反參考。

首先,讓我們寫一個有 u8 欄位的結構。然後,我們將對它做參考,並嘗試進行比較。它將無法執行:

struct Item {
    number: u8,
}

fn main() {
    let item = Item {
        number: 8,
    };

    let reference_number = &item.number; // 型別是 &u8

    println!("{}", reference_number == 8); // ⚠️ &u8 和 u8 不能比較
}

為了讓它能執行,我們需要去反參考:println!("{}", *reference_number == 8);

但用了點運算子,我們就不需要*。例如:

struct Item {
    number: u8,
}

fn main() {
    let item = Item {
        number: 8,
    };

    let reference_item = &item;

    println!("{}", reference_item.number == 8); // 我們不要需寫成 *reference_item.number
}

現在讓我們為 Item 建立方法來比較 number 與另一個數字。我們不需要在任何地方使用 *

struct Item {
    number: u8,
}

impl Item {
    fn compare_number(&self, other_number: u8) { // 接受 self 的參考
        println!("Are {} and {} equal? {}", self.number, other_number, self.number == other_number);
            // 我們不需要寫 *self.number
    }
}

fn main() {
    let item = Item {
        number: 8,
    };

    let reference_item = &item; // 型別 &Item
    let reference_item_two = &reference_item; // 型別 &&Item

    item.compare_number(8); // 方法可以執行
    reference_item.compare_number(8); // 它在這裡也可以執行
    reference_item_two.compare_number(8); // 還有這裡

}

所以只要記住:當你使用 . 運算子時,你不需要擔心有沒有 *