C++ 的存儲類別

你好,有抱負的程式設計師們!今天,我們將踏上一段令人興奮的旅程,探索C++存儲類別的世界。別擔心如果你是編程新手;我將成為你友好的導遊,逐步解釋一切。讓我們一起來看看吧!

C++ Storage Classes

什麼是存儲類別?

在我們深入具體內容之前,讓我們先了解存儲類別是什麼。在C++中,存儲類別定義了變量和函數在程序中的作用域(可見性)和生命周期。它們告訴編譯器如何存儲變量,它是否從其他文件中可訪問,以及它在記憶體中應該存在多長時間。

現在,讓我們詳細探索每種存儲類別。

auto 存儲類別

在C++中,auto關鍵字隨著時間的推移改變了它的含義。在現代C++(C++11及之後版本)中,它用於類型推斷。然而,在較舊的版本中,它是一個存儲類別指定符。

舊用法(C++11之前):

int main() {
auto int x = 5;  // 等價於:int x = 5;
return 0;
}

在這個舊用法中,auto明確聲明了一個具有自動存儲周期的變量。然而,這是本地變量的默認設定,所以很少使用。

現代用法(C++11及之後):

int main() {
auto x = 5;  // x被推斷為int
auto y = 3.14;  // y被推斷為double
auto z = "Hello";  // z被推斷為const char*
return 0;
}

在現代C++中,auto讓編譯器根據初始化器推斷變量的類型。當類型可能變化或在將來變化時,它特別有用。

register 存儲類別

register關鍵字是給編譯器的暗示,表示這個變量將被大量使用,並應該保持在CPU寄存器中以供快速訪問。

#include <iostream>

int main() {
register int counter = 0;

for(int i = 0; i < 1000000; i++) {
counter++;
}

std::cout << "計數器: " << counter << std::endl;
return 0;
}

在這個例子中,我們建議編譯器將counter保持在寄存器中。然而,現代編譯器通常足夠聰明,能夠自行進行這些優化,所以register在實踐中很少使用。

static 存儲類別

static關鍵字根據其使用位置有不同的含義:

1. 靜態本地變量

#include <iostream>

void countCalls() {
static int calls = 0;
calls++;
std::cout << "這個函數已被調用 " << calls << " 次。" << std::endl;
}

int main() {
for(int i = 0; i < 5; i++) {
countCalls();
}
return 0;
}

在這個例子中,calls只初始化一次,並在函數調用之間保持其值。輸出將會是:

這個函數已被調用 1 次。
這個函數已被調用 2 次。
這個函數已被調用 3 次。
這個函數已被調用 4 次。
這個函數已被調用 5 次。

2. 靜態類成員

class MyClass {
public:
static int objectCount;

MyClass() {
objectCount++;
}
};

int MyClass::objectCount = 0;

int main() {
MyClass obj1;
MyClass obj2;
MyClass obj3;

std::cout << "創建的物件數量: " << MyClass::objectCount << std::endl;
return 0;
}

在這裡,objectCount在所有MyClass的實例之間共享。輸出將會是:

創建的物件數量: 3

extern 存儲類別

extern關鍵字用於在另一個文件中聲明全局變量或函數。

文件:globals.cpp

int globalVar = 10;

文件:main.cpp

#include <iostream>

extern int globalVar;  // 聲明 globalVar

int main() {
std::cout << "全局變量值: " << globalVar << std::endl;
return 0;
}

在這個例子中,globalVarglobals.cpp中定義,並在main.cpp中作為extern聲明。這樣main.cpp就可以使用在另一個文件中定義的變量。

mutable 存儲類別

mutable關鍵字允許const對象的成員被修改。

class Person {
public:
Person(int age) : age(age), cacheValid(false) {}

int getAge() const {
if (!cacheValid) {
cachedAge = heavyComputation();
cacheValid = true;
}
return cachedAge;
}

private:
int age;
mutable int cachedAge;
mutable bool cacheValid;

int heavyComputation() const {
// 模擬一個耗時計算
return age;
}
};

int main() {
const Person p(30);
std::cout << p.getAge() << std::endl;  // 這是允許的
return 0;
}

在這個例子中,即使p是const,我們也可以修改cachedAgecacheValid,因為它們被標記為mutable

總結

讓我們總結一下我們學到的存儲類別,並提供一個方便的表格:

存儲類別 用途
auto 類型推斷(現代C++)
register 快速訪問的暗示(很少使用)
static 在函數調用之間保持值或類實例間共享
extern 在其他文件中聲明變量或函數
mutable 在const對象中允許修改

記住,理解存儲類別對於有效地管理記憶體和控制變量的作用域至關重要。隨著你繼續在C++的旅程上前行,你會發現這些概念變得習以為常。祝你編程愉快!

Credits: Image by storyset