Skip to content

C++ 存储类

存储类决定了变量的生命周期、可见性和存储位置。C++ 中有以下存储类:

  1. auto:自动存储类
  2. register:寄存器存储类
  3. static:静态存储类
  4. extern:外部存储类
  5. mutable:可变存储类
  6. 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++ 存储类包括:

  1. auto:自动存储类,是局部变量的默认存储类
  2. register:寄存器存储类,建议编译器将变量存储在寄存器中
  3. static:静态存储类,使变量在程序的整个执行期间都存在
  4. extern:外部存储类,用于声明在其他文件中定义的全局变量
  5. mutable:可变存储类,允许在const成员函数中修改成员变量
  6. thread_local:线程局部存储类(C++11),使变量在每个线程中都有独立的副本

关键概念:

  • 生命周期:变量存在的时间范围
  • 可见性:变量可以被访问的范围
  • 存储位置:变量存储在内存中的位置

选择合适的存储类对于编写高效、正确的程序非常重要。在后续章节中,我们将学习 C++ 的运算符。