Appearance
C++ 存储类
存储类决定了变量的生命周期、可见性和存储位置。C++ 中有以下存储类:
- auto:自动存储类
- register:寄存器存储类
- static:静态存储类
- extern:外部存储类
- mutable:可变存储类
- thread_local:线程局部存储类(C++11)
1. auto 存储类
auto存储类是局部变量的默认存储类。auto变量在进入作用域时创建,在离开作用域时销毁。
1.1 基本用法
cpp
#include <iostream>
int main() {
auto int a = 10; // 等同于 int a = 10;
auto b = 20; // 自动推导为 int
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
return 0;
}1.2 auto 的现代用法(C++11)
从 C++11 开始,auto关键字用于自动类型推导:
cpp
#include <iostream>
#include <vector>
int main() {
auto i = 10; // 推导为 int
auto d = 3.14; // 推导为 double
auto str = "hello"; // 推导为 const char*
std::vector<int> v = {1, 2, 3};
auto it = v.begin(); // 推导为 std::vector<int>::iterator
std::cout << "i = " << i << std::endl;
std::cout << "d = " << d << std::endl;
std::cout << "str = " << str << std::endl;
std::cout << "*it = " << *it << std::endl;
return 0;
}2. register 存储类
register存储类建议编译器将变量存储在寄存器中以提高访问速度。现代编译器通常会自动优化,因此register的使用已经很少。
2.1 基本用法
cpp
#include <iostream>
int main() {
register int counter = 0; // 建议存储在寄存器中
for (int i = 0; i < 1000000; i++) {
counter++;
}
std::cout << "counter = " << counter << std::endl;
return 0;
}2.2 register 的限制
- 不能获取
register变量的地址 register变量必须是单个值- 不能用于全局变量
cpp
#include <iostream>
int main() {
register int x = 10;
// int* ptr = &x; // 错误:不能获取 register 变量的地址
return 0;
}3. static 存储类
static存储类使变量在程序的整个执行期间都存在,而不是在每次进入作用域时重新创建。
3.1 静态局部变量
静态局部变量只在第一次声明时初始化,之后保持其值:
cpp
#include <iostream>
void counter() {
static int count = 0; // 静态局部变量
count++;
std::cout << "count = " << count << std::endl;
}
int main() {
counter(); // 输出: count = 1
counter(); // 输出: count = 2
counter(); // 输出: count = 3
return 0;
}3.2 静态全局变量
静态全局变量只能在定义它的文件中访问:
cpp
// file1.cpp
static int global_var = 100; // 静态全局变量
void function() {
std::cout << global_var << std::endl;
}
// file2.cpp
// extern int global_var; // 错误:无法访问静态全局变量3.3 静态成员变量
静态成员变量在所有对象之间共享:
cpp
#include <iostream>
class Counter {
private:
static int count; // 静态成员变量
public:
Counter() {
count++;
}
~Counter() {
count--;
}
static int get_count() {
return count;
}
};
// 初始化静态成员变量
int Counter::count = 0;
int main() {
Counter c1;
Counter c2;
Counter c3;
std::cout << "对象数量: " << Counter::get_count() << std::endl; // 输出: 3
{
Counter c4;
std::cout << "对象数量: " << Counter::get_count() << std::endl; // 输出: 4
}
std::cout << "对象数量: " << Counter::get_count() << std::endl; // 输出: 3
return 0;
}3.4 静态成员函数
静态成员函数只能访问静态成员变量:
cpp
#include <iostream>
class Example {
private:
static int count; // 静态成员变量
int value; // 非静态成员变量
public:
Example(int v) : value(v) {
count++;
}
static int get_count() {
return count; // 可以访问静态成员变量
// return value; // 错误:不能访问非静态成员变量
}
int get_value() {
return value;
}
};
int Example::count = 0;
int main() {
Example e1(10);
Example e2(20);
std::cout << "对象数量: " << Example::get_count() << std::endl; // 输出: 2
std::cout << "e1 的值: " << e1.get_value() << std::endl; // 输出: 10
return 0;
}4. extern 存储类
extern存储类用于声明在其他文件中定义的全局变量。
4.1 基本用法
cpp
// file1.cpp
int global_var = 100;
// file2.cpp
#include <iostream>
extern int global_var; // 声明在 file1.cpp 中定义的变量
int main() {
std::cout << "global_var = " << global_var << std::endl; // 输出: 100
return 0;
}4.2 extern 与 const
默认情况下,const全局变量具有内部链接,需要在定义时添加extern才能在其他文件中访问:
cpp
// file1.cpp
extern const int MAX_SIZE = 100;
// file2.cpp
#include <iostream>
extern const int MAX_SIZE; // 声明在 file1.cpp 中定义的常量
int main() {
std::cout << "MAX_SIZE = " << MAX_SIZE << std::endl; // 输出: 100
return 0;
}5. mutable 存储类
mutable存储类允许在const成员函数中修改成员变量。
5.1 基本用法
cpp
#include <iostream>
class Example {
private:
mutable int count; // 可变成员变量
int value;
public:
Example(int v) : value(v), count(0) {}
int get_value() const {
count++; // 可以修改可变成员变量
return value;
}
int get_count() const {
return count;
}
};
int main() {
const Example e(10);
std::cout << "value = " << e.get_value() << std::endl; // 输出: 10
std::cout << "count = " << e.get_count() << std::endl; // 输出: 1
std::cout << "value = " << e.get_value() << std::endl; // 输出: 10
std::cout << "count = " << e.get_count() << std::endl; // 输出: 2
return 0;
}6. thread_local 存储类(C++11)
thread_local存储类使变量在每个线程中都有独立的副本。
6.1 基本用法
cpp
#include <iostream>
#include <thread>
thread_local int thread_var = 0;
void function(int id) {
thread_var = id;
std::cout << "线程 " << id << ": thread_var = " << thread_var << std::endl;
}
int main() {
std::thread t1(function, 1);
std::thread t2(function, 2);
t1.join();
t2.join();
return 0;
}7. 存储类的比较
| 存储类 | 生命周期 | 可见性 | 存储位置 |
|---|---|---|---|
auto | 作用域内 | 作用域内 | 栈 |
register | 作用域内 | 作用域内 | 寄存器(可能) |
static(局部) | 程序执行期间 | 作用域内 | 静态存储区 |
static(全局) | 程序执行期间 | 文件内 | 静态存储区 |
extern | 程序执行期间 | 全局 | 静态存储区 |
mutable | 取决于对象 | 取决于对象 | 取决于对象 |
thread_local | 线程执行期间 | 线程内 | 线程局部存储 |
8. 示例:综合运用
现在,让我们看一个综合运用各种存储类的例子:
cpp
#include <iostream>
#include <vector>
// 全局变量
int global_var = 100;
static int static_global_var = 200;
// 类
class Counter {
private:
static int count; // 静态成员变量
mutable int access_count; // 可变成员变量
int value;
public:
Counter(int v) : value(v), access_count(0) {
count++;
}
~Counter() {
count--;
}
int get_value() const {
access_count++; // 可以修改可变成员变量
return value;
}
int get_access_count() const {
return access_count;
}
static int get_count() {
return count;
}
};
// 初始化静态成员变量
int Counter::count = 0;
// 函数
void demonstrate_auto() {
auto int a = 10; // 自动变量
auto b = 20; // 自动类型推导
std::cout << "auto 变量: " << a << ", " << b << std::endl;
}
void demonstrate_static_local() {
static int count = 0; // 静态局部变量
count++;
std::cout << "静态局部变量 count = " << count << std::endl;
}
void demonstrate_register() {
register int counter = 0; // 寄存器变量
for (int i = 0; i < 10; i++) {
counter++;
}
std::cout << "寄存器变量 counter = " << counter << std::endl;
}
int main() {
// 演示 auto 存储类
std::cout << "auto 存储类:" << std::endl;
demonstrate_auto();
// 演示 static 局部变量
std::cout << "\nstatic 局部变量:" << std::endl;
demonstrate_static_local();
demonstrate_static_local();
demonstrate_static_local();
// 演示 register 存储类
std::cout << "\nregister 存储类:" << std::endl;
demonstrate_register();
// 演示全局变量
std::cout << "\n全局变量:" << std::endl;
std::cout << "global_var = " << global_var << std::endl;
std::cout << "static_global_var = " << static_global_var << std::endl;
// 演示静态成员变量和可变成员变量
std::cout << "\n静态成员变量和可变成员变量:" << std::endl;
Counter c1(10);
Counter c2(20);
Counter c3(30);
std::cout << "对象数量: " << Counter::get_count() << std::endl;
std::cout << "c1 的值: " << c1.get_value() << std::endl;
std::cout << "c1 的访问次数: " << c1.get_access_count() << std::endl;
std::cout << "c2 的值: " << c2.get_value() << std::endl;
std::cout << "c2 的访问次数: " << c2.get_access_count() << std::endl;
return 0;
}小结
C++ 存储类包括:
- auto:自动存储类,是局部变量的默认存储类
- register:寄存器存储类,建议编译器将变量存储在寄存器中
- static:静态存储类,使变量在程序的整个执行期间都存在
- extern:外部存储类,用于声明在其他文件中定义的全局变量
- mutable:可变存储类,允许在
const成员函数中修改成员变量 - thread_local:线程局部存储类(C++11),使变量在每个线程中都有独立的副本
关键概念:
- 生命周期:变量存在的时间范围
- 可见性:变量可以被访问的范围
- 存储位置:变量存储在内存中的位置
选择合适的存储类对于编写高效、正确的程序非常重要。在后续章节中,我们将学习 C++ 的运算符。