C++ 存储器

在 C++ 中,存储类(Storage Class)决定了变量或函数的范围(Scope)生命周期(Lifetime)可见性(Visibility)存储位置(Storage Location)。理解存储类对于编写高效和正确的 C++ 代码至关重要。

1. 常见存储类及其定义

C++ 提供了以下几种存储类:

  1. auto(自动存储类):

    • 范围:局部变量(函数内)
    • 生命周期:当程序执行到该变量的声明时分配内存,并在离开变量作用域时释放。
    • 使用注意:C++11 之后,auto 主要用于自动类型推导,而不是存储类说明符。
  2. register(寄存器存储类):

    • 范围:局部变量
    • 生命周期:与 auto 类似。
    • 存储位置:尽量存储在 CPU 寄存器中以提高访问速度,但并不保证一定会在寄存器中存储。
    • 使用注意:现代编译器一般会自动优化寄存器分配,因此 register 现在很少使用。
  3. static(静态存储类):

    • 范围:局部变量(函数内)或全局变量(文件范围内)
    • 生命周期:在程序的整个生命周期内保持不变。即使在函数内定义的静态变量也是如此,它们在第一次初始化后将一直存在。
    • 使用注意:静态局部变量只会被初始化一次,且在函数调用结束后仍保持其值。静态全局变量(文件范围内的变量)只能在定义它的文件中可见。
  4. extern(外部存储类):

    • 范围:全局变量(或函数)
    • 生命周期:与程序生命周期一致。
    • 使用注意extern 用于声明变量或函数的引用,而不是定义。通常在一个文件中声明,在另一个文件中定义,用于多文件程序的变量或函数共享。
  5. mutable(可变存储类):

    • 范围:类成员变量
    • 生命周期:随对象的生命周期而变化。
    • 使用注意:即使在 const 成员函数中,mutable 变量也可以被修改。
  6. thread_local(线程局部存储类):

    • 范围:全局变量、函数内的局部变量或静态成员变量
    • 生命周期:在每个线程的生命周期内。
    • 使用注意:每个线程都有该变量的独立实例,适用于需要在不同线程中保持独立状态的数据。

2. 使用示例(Demo)

下面的代码展示了每种存储类的用法:

#include <iostream>
using namespace std;

// 全局变量,默认存储类为 extern
int g_count = 0;

void autoDemo() {
    auto num = 10;  // 自动类型推导
    cout << "auto num: " << num << endl;
}

void staticDemo() {
    static int count = 0; // 静态局部变量
    cout << "static count: " << count << endl;
    count++;
}

void registerDemo() {
    register int regVar = 0; // 寄存器变量
    cout << "register var: " << regVar << endl;
}

class Demo {
public:
    mutable int mutableVar; // 可变成员变量
    Demo() : mutableVar(0) {}
    void setValue(int val) const {
        mutableVar = val;
    }
};

void threadLocalDemo() {
    thread_local int threadVar = 1; // 线程局部变量
    cout << "thread_local var: " << threadVar << endl;
    threadVar++;
}

int main() {
    // extern 变量的使用
    extern int g_count; // 引用全局变量
    cout << "extern g_count: " << g_count << endl;

    // auto 示例
    autoDemo();

    // static 示例
    for (int i = 0; i < 3; i++) {
        staticDemo();
    }

    // register 示例
    registerDemo();

    // mutable 示例
    Demo demo;
    demo.setValue(100);
    cout << "mutable var: " << demo.mutableVar << endl;

    // thread_local 示例
    threadLocalDemo();
    threadLocalDemo(); // 第二次调用

    return 0;
}
运行结果:

extern g_count: 0
auto num: 10
static count: 0
static count: 1
static count: 2
register var: 0
mutable var: 100
thread_local var: 1
thread_local var: 2

3. 注意事项和常见坑

  1. autoregister:在 C++11 之后,auto 主要用于类型推导,register 的使用已逐渐被编译器优化所取代,因此一般不需要手动指定。

  2. static 变量的初始化:静态局部变量在函数第一次调用时初始化,并且在后续调用中保留其值,容易导致意外行为。因此使用静态变量时要注意逻辑设计,避免错误的初始化或状态遗留。

  3. extern 和 多文件编程:使用 extern 时,确保在一个文件中定义全局变量,在其他文件中声明它。避免重复定义全局变量,这会导致链接错误。

  4. thread_local 的性能thread_local 变量在每个线程都有独立的副本,这会增加一定的内存开销和访问开销。需要在性能敏感的地方谨慎使用。

  5. mutable 的可变性mutable 允许在 const 成员函数中修改类成员,这在设计类时要小心使用,以避免违反类的不变性原则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值