變數範圍 Scope

在「作用域」這一節中,我們介紹了 內部連結外部連結 等等觀念。這章我們要來介紹更為基礎的觀念:變數範圍 Scope。

一樣我們會先了解什麼是變數範圍,看看有哪幾種範圍,接著舉幾個例子讓我們可以更容易理解!

什麼是變數範圍

前一章我們有提到什麼是 全局變數 global variable,與之相反的,我們有區域變數 local variable,另外還有區塊變數 block variable。

這些有不同名稱的變數,雖然都是變數,但是作用的範圍卻不相同。

這些「全局」、「區域」、「區塊」等概念,被我們稱作變數(作用)範圍。

舉例來說,我們已經知道全局變數的作用範圍在整個軟體專案,代表不僅僅是當前的文件可以看到這個變數,任何其他在同一專案的文件都可以看到這個全局變數。

那麼什麼是區域變數?什麼又是區塊變數呢?

區域變數

區域變數英文稱作 local variable。區域變數指的是函數中宣告的變數,或是宣告在參數列的參數,範圍只在函數之內。

我們來看個例子:

int add(int a, int b)
{
    int c = a + b;
    return c;
}

這裡看到的變數 abc 都是區域變數,作用都只存在於這個函數之內。

生命週期

在 C++ 中,每個變數都有一個「生命週期」,英文叫做 lifetime。

一個變數的生命週期始於他被創造時,終於他被銷毀時。而在一個變數的生命週期之內,它所可以行經的路徑,就是它的範圍。

我們來看看上面的例子中,變數 abc 的生命週期為何。

int add(int a, int b)    // a 和 b 在這裡被創造
{
    int c = a + b;       // c 在這裡被創造
    return c;
}    // a, b, c 在這裡被銷毀

我們可以註解中看到,這三個變數都創造與銷毀都在函數開始與結束之間,因此,這些變數的作用範圍只會在這個函數之內。

也因為這樣,這三個變數在這裡都被叫做區域變數 local variable。

區塊變數

區塊變數英文稱作 block variable。區塊變數指的是某區塊中的變數,比如說 while 迴圈區塊、 for 迴圈區塊、或是任何由 {} 包括起來的區塊。

同樣的,這些變數的作用範圍只存在於這些區塊之內。

我們來看個例子:

for (int i = 0; i < 10; ++i)
{
    ...
}

這裡看到的變數 i 則是區塊變數,作用也只存在於這個 for 迴圈之內。

我們來看看另一個例子:

int main()
{
    int a = 0;
    {
        int b = 3;
    }
    return 0;
}

這裡看到的變數 ab 也都是區塊變數,因為都被 {} 給包裹著。

生命週期

在第一個例子中,變數 i 的生命週期應該非常明顯吧!

for(int i = 0; i < 10; ++i)    // i 在這裡被創造
{
    ...
}    // i 在這裡被銷毀

我們可以看到,變數 i 被創造以及被銷毀的時間都在這個 for 迴圈之內,因此這個變數的作用範圍只存在於迴圈之內。

接著我們來看第二個例子

int main()
{
    int a = 0;        // a 在這裡被創造
    {
        int b = 3;    // b 在這裡被創造
    }                 // b 在這裡被銷毀
    return 0;
}                     // a 在這裡被銷毀

我們可以發現,變數 b 並沒有和變數 a 同一時間銷毀,而是提早銷毀了!

這是非常重要的觀念!變數必須在被創造的同一層結束時被銷毀!

也就是說,如果我嘗試在外圈取得變數 b,比如說

int main()
{
    int a = 0;
    {
        int b = 3;
    }
    b = 4;    // 嘗試在內圈以外取得 b
    return 0;
}

那麼程式就會報錯,因為他在外圈並不會認得變數 b

最佳實踐

現在我們都知道變數有不同的作用範圍,取決於它存在的位置,以及我們什麼時候創建它。

基於這個原因,一個好的程式碼應該遵行這個準則:「在只有需要用到該變數的區塊內才創建該變數。」

比如說:

int main()
{
    // 不要在這裡創建 x
    {
        // 程式碼只有在內部的 {} 才會用到 x
        int x = 0;
        x = x + 3;
    }
    return 0;
}

在上面的例子中,由於程式碼只需要在內部 {} 才會用到變數 x,因此我們不需要在外部就創建 x

這麼做有很大的好處,最顯著的好處是這樣做可以降低程式的複雜性。另外,我們還可以更輕鬆地查看變數在何處使用、何處未使用。

區塊內定義的變數只能在該區塊內使用,這讓我們寫出來的程式碼更容易理解。

總結

這章我們了解了非常基礎但重要的觀念:變數範圍,包括它是什麼、它的變化等等。

基本上,就是在讓我們知道不同變數被創建以及被銷毀的時機。

接下來我們就要進入下一節,也是 C++ 中更為進階的概念:物件導向及類別。