變數範圍 Scope
在「作用域」這一節中,我們介紹了 內部連結、外部連結 等等觀念。這章我們要來介紹更為基礎的觀念:變數範圍 Scope。
一樣我們會先了解什麼是變數範圍,看看有哪幾種範圍,接著舉幾個例子讓我們可以更容易理解!
什麼是變數範圍
前一章我們有提到什麼是 全局變數 global variable,與之相反的,我們有區域變數 local variable,另外還有區塊變數 block variable。
這些有不同名稱的變數,雖然都是變數,但是作用的範圍卻不相同。
這些「全局」、「區域」、「區塊」等概念,被我們稱作變數(作用)範圍。
舉例來說,我們已經知道全局變數的作用範圍在整個軟體專案,代表不僅僅是當前的文件可以看到這個變數,任何其他在同一專案的文件都可以看到這個全局變數。
那麼什麼是區域變數?什麼又是區塊變數呢?
區域變數
區域變數英文稱作 local variable。區域變數指的是函數中宣告的變數,或是宣告在參數列的參數,範圍只在函數之內。
我們來看個例子:
int add(int a, int b) { int c = a + b; return c; }
這裡看到的變數 a
、b
、c
都是區域變數,作用都只存在於這個函數之內。
生命週期
在 C++ 中,每個變數都有一個「生命週期」,英文叫做 lifetime。
一個變數的生命週期始於他被創造時,終於他被銷毀時。而在一個變數的生命週期之內,它所可以行經的路徑,就是它的範圍。
我們來看看上面的例子中,變數 a
、b
、c
的生命週期為何。
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; }
這裡看到的變數 a
和 b
也都是區塊變數,因為都被 {}
給包裹著。
生命週期
在第一個例子中,變數 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++ 中更為進階的概念:物件導向及類別。