昨天我們介紹完了變數的用法,那麼今天來介紹一下變數的作用域。

作用域

作用域,也就是變數的有效範圍。

一般程式語言在宣告變數後,變數都有它的有效區域。可以把他想成把一個球員派上場,他的活動範圍就會在某個區塊。

而 Rust 也不例外,可以看下方的範例,x 這個變數在大括號中都是有效範圍。
而在大括號中又建立了一個大括號,並且宣告了一個變數 y,這裡我們給一個註解叫做 y 區塊,比較好辨識,並且要用 println!xy 給印出來。

1
2
3
4
5
6
7
8
fn main() {
let x = 10;
// y 區塊
{
let y = 20;
println!("x: {}, y: {}", x, y);
}
}

最終也可以成功印出 x: 10, y: 20
雖然在 y 區塊中,並沒有宣告 x,但是由於在 main(){} 中這個大括號已經有宣告,而 x 的作用域在整個 main(){} 中都是有效的,所以才能夠得到兩者的結果。

那麼如果是下方的範例,多加了一行會是怎樣呢?

1
2
3
4
5
6
7
8
9
fn main() {
let x = 10;
// y 區塊
{
let y = 20;
println!("x: {}, y: {}", x, y);
}
println!("x: {}, y: {}", x, y);
}

因為 Rust 在處理區塊時,執行完後會刪除該區塊,也沒有垃圾回收機制。所以在 y 區塊執行完後會立即刪除,這也就表示最後一次要印出 y 是沒有作用的,而且 VSCode 會提示你說找不到 y,所以在寫 Rust 時,務必要注意作用域的範圍。

https://ithelp.ithome.com.tw/upload/images/20220919/20120293ZolaojnVxN.png

遮蔽

一樣先給範例:

1
2
3
4
5
6
7
8
9
fn main() {
let x = 10;
{
println!("x: {}", x); // 第一次列印
let x = 20;
println!("x: {}", x); // 第二次列印
}
println!("x: {}", x); // 第三次列印
}

在這個例子中,宣告了變數 x,並且在區塊中列印該變數。
而在第一次列印完後,把之前的的變數再次宣告新的變數。也就是用 let x = 遮蔽了 x 變數,並取代了原本的變數改成 20。
所以第一次列印結果會是 10,第二次列印結果會是 20。
而到了第三次列印,由於區塊已經執行完畢,所以該區塊會立即刪除,這時候得到的結果就是 10。

再看一個例子,並可以試著猜看看結果:

1
2
3
4
5
6
7
8
9
fn main() {
let x = 10;
let x = x + 2;
{
let x = x * 2;
println!("x: {}", x); // 第一次列印
}
println!("x: {}", x); // 第二次列印
}

來講解一下這裡是怎麼運作的。
首先宣告一個 x,並且賦予值為 10。
接著在同一個作用域中遮蔽了 x 並用原本的值 10 再加 2,這時候 x 就會是 12。
然後建立了一個區塊,在區塊中又遮蔽了 X 並且把現有的值 12 再乘 2,這時候在區塊中的 x 的值會是 24,所以第一次列印結果會是 24。
區塊執行完被刪除,這時候的 x 就會回到區塊中遮蔽前的狀態,所以第二次列印結果會是 12。

最後要講一下,遮蔽也可以拿來運用原有變數改變型別,例如以下範例:

1
2
3
4
5
fn main() {
let y = 10;
let y = "Ten";
println!("y: {}", y);
}

一開始先宣告 y 變數,並且賦予值為 10。
接著遮蔽並改變值跟型別為字串 “Ten",最後印出結果為 Ten。

以上就是變數作用域的部分,感謝你看完本篇文章。