1. static
變數的初始化與賦值
static
變數在 C++ 中有一個特別的性質:它們在程式的生命週期內只會被初始化一次,但之後可以繼續對其進行賦值。
-
初始化:
static
變數在程式的初始化階段(即程式第一次執行時)會被初始化一次。如果是區域性static
變數,則它會在第一次執行到該變數所在的程式碼行時被初始化;如果是全域性或靜態作用域內的變數,則會在程式啟動時初始化。 -
賦值:初始化之後,
static
變數的值是可以改變的。賦值操作不會改變static
變數的記憶體地址,也就是說,static
變數的記憶體地址在整個程式執行期間是固定的。賦值只會改變該記憶體地址中儲存的資料,而不會影響變數的地址。
示例:static
變數的初始化和賦值
#include <iostream>
void testStatic() {
static int x = 10; // 初始化只發生一次
std::cout << "x = " << x << std::endl;
x = 20; // 賦值,但不重新初始化
std::cout << "x after assignment = " << x << std::endl;
}
int main() {
testStatic(); // 第一次呼叫,初始化並賦值為 10
testStatic(); // 第二次呼叫,x 已初始化,賦值為 20
return 0;
}
輸出:
x = 10
x after assignment = 20
x = 20
x after assignment = 20
在這個例子中,x
是 static
變數:
- 第一次呼叫
testStatic()
時,x
會被初始化為 10,之後賦值為 20。 - 第二次呼叫
testStatic()
時,x
不會重新初始化,而是保持上次賦的值(20),並可以繼續賦值。
記憶體地址不變:無論你如何對 x
進行賦值,x
的記憶體地址始終不變,它依然指向同一塊記憶體位置。
2. 普通變數的初始化與賦值
對於普通的區域性變數,每次進入其作用域時,該變數會被重新初始化,並且會在棧上分配新的記憶體空間。普通變數 可以多次初始化,但每次進入作用域時,都會重新為該變數分配記憶體(除非它是動態分配的,如使用 new
)。
- 初始化:每次進入作用域時,區域性變數都會被重新初始化,並且會重新分配棧空間。
- 賦值:可以在初始化之後對普通變數進行賦值,但賦值不等於初始化。賦值操作會改變該變數儲存的值,而不會影響它的記憶體位置(除非你是指標型別)。
示例:普通區域性變數的初始化和賦值
#include <iostream>
void testNormal() {
int x = 10; // 每次進入函式時都會初始化
std::cout << "x = " << x << std::endl;
x = 20; // 賦值,但記憶體地址不變
std::cout << "x after assignment = " << x << std::endl;
}
int main() {
testNormal(); // 第一次呼叫,初始化為 10
testNormal(); // 第二次呼叫,重新初始化為 10
return 0;
}
輸出:
x = 10
x after assignment = 20
x = 10
x after assignment = 20
在這個例子中,x
是普通的區域性變數:
- 每次呼叫
testNormal()
時,x
會被重新初始化,並且會重新分配棧空間。 x
的值在初始化後可以被賦值為其他值,但它的記憶體地址在每次呼叫testNormal()
時都是新的,棧空間會被重新分配。
3. 對比:static
變數與普通變數的差異
特性 | static 變數 | 普通區域性變數 |
---|---|---|
初始化 | 只初始化一次,在程式啟動或首次呼叫時初始化 | 每次進入作用域時初始化 |
賦值 | 之後可以多次賦值,但不改變記憶體地址 | 可以多次賦值,但記憶體地址隨每次進入作用域不同 |
記憶體管理 | 只有一塊記憶體空間,記憶體地址固定 | 每次進入作用域時會重新分配記憶體 |
生命週期 | 整個程式執行期間(從程式啟動到結束) | 僅在作用域內有效,出作用域時銷燬 |
4. 棧空間與堆空間的對比(記憶體分配)
-
棧空間(stack):區域性變數(普通變數)通常儲存在棧上。每次進入作用域時,棧空間會為變數分配記憶體,離開作用域時銷燬。這是 自動記憶體管理。
-
堆空間(heap):使用
new
或malloc
分配的記憶體則來自堆。堆上的記憶體通常需要顯式釋放(如透過delete
或free
),否則會導致記憶體洩漏。
5. 結論
static
變數:初始化只發生一次,記憶體地址在整個程式的生命週期內固定,不會發生變化。之後的賦值只是改變其儲存的值,而不會改變記憶體地址。- 普通區域性變數:每次進入作用域時會重新分配記憶體,並且會重新初始化。因此,每次函式呼叫時,區域性變數的記憶體空間是不同的。
總結來說,static
變數不會在每次呼叫時重新分配記憶體,它的記憶體地址是固定的,而普通區域性變數每次進入作用域時都會重新分配記憶體,記憶體地址不同。