C++ 存储类
你好,有抱负的程序员们!今天,我们将踏上一段激动人心的旅程,探索 C++ 存储类的世界。如果你是编程新手,不用担心;我将作为你友好的向导,一步步解释所有内容。让我们开始吧!
什么是存储类?
在我们具体讨论之前,让我们先了解一下存储类是什么。在 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: " << counter << std::endl;
return 0;
}
在这个例子中,我们建议编译器 counter
应该保持在寄存器中。然而,现代编译器通常足够智能,能够自己进行这些优化,所以 register
在实际中很少使用。
static 存储类
static
关键字根据其使用的位置有不同的含义:
1. 静态局部变量
#include <iostream>
void countCalls() {
static int calls = 0;
calls++;
std::cout << "This function has been called " << calls << " times." << std::endl;
}
int main() {
for(int i = 0; i < 5; i++) {
countCalls();
}
return 0;
}
在这个例子中,calls
只被初始化一次,并在函数调用之间保持其值。输出将是:
This function has been called 1 times.
This function has been called 2 times.
This function has been called 3 times.
This function has been called 4 times.
This function has been called 5 times.
2. 静态类成员
class MyClass {
public:
static int objectCount;
MyClass() {
objectCount++;
}
};
int MyClass::objectCount = 0;
int main() {
MyClass obj1;
MyClass obj2;
MyClass obj3;
std::cout << "Number of objects created: " << MyClass::objectCount << std::endl;
return 0;
}
在这里,objectCount
在所有 MyClass
实例之间共享。输出将是:
Number of objects created: 3
extern 存储类
extern
关键字用于在另一个文件中声明全局变量或函数。
文件:globals.cpp
int globalVar = 10;
文件:main.cpp
#include <iostream>
extern int globalVar; // 声明 globalVar
int main() {
std::cout << "Global variable value: " << globalVar << std::endl;
return 0;
}
在这个例子中,globalVar
在 globals.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,我们仍然可以修改 cachedAge
和 cacheValid
,因为它们被标记为 mutable
。
总结
让我们总结一下我们学到的存储类,并在一个方便的表格中展示:
存储类 | 目的 |
---|---|
auto | 类型推断(现代 C++) |
register | 提示更快访问(很少使用) |
static | 在函数调用之间保持值或在类实例之间共享 |
extern | 声明其他文件中的变量或函数 |
mutable | 允许 const 对象中的成员被修改 |
记住,理解存储类对于有效地管理内存和控制变量的作用域至关重要。随着你继续你的 C++ 之旅,你会发现这些概念变得习以为常。祝你编程愉快!
Credits: Image by storyset