Skip to content

C++ 存储类

概述

存储类(Storage Class)指定了变量和函数的存储位置、生命周期、作用域和链接属性。C++提供了多种存储类说明符,正确理解和使用存储类对于编写高效、正确的C++程序至关重要。

🏗️ 存储类分类

存储类概览

mermaid
graph TD
    A[C++存储类] --> B[auto]
    A --> C[register]
    A --> D[static]
    A --> E[extern]
    A --> F[mutable]
    A --> G[thread_local]
    
    B --> B1[自动存储期]
    C --> C1[寄存器存储期]
    D --> D1[静态存储期]
    E --> E1[外部链接]
    F --> F1[可变成员]
    G --> G1[线程局部存储]

🚗 auto存储类

传统auto(C++11之前)

cpp
#include <iostream>

// 在C++11之前,auto表示自动存储期(通常省略)
void traditional_auto_demo() {
    auto int x = 10;        // 等同于 int x = 10;
    auto double y = 3.14;   // 等同于 double y = 3.14;
    
    // auto是默认的存储类,通常省略
    int a = 20;             // 等同于 auto int a = 20;
    double b = 2.71;        // 等同于 auto double b = 2.71;
    
    std::cout << "传统auto变量: x=" << x << ", y=" << y << std::endl;
    std::cout << "默认auto变量: a=" << a << ", b=" << b << std::endl;
}

现代auto(C++11及以后)

cpp
#include <iostream>
#include <vector>
#include <string>
#include <map>

void modern_auto_demo() {
    // 现代auto:类型推导
    auto integer = 42;              // int
    auto floating = 3.14;           // double
    auto character = 'A';           // char
    auto text = "Hello";            // const char*
    auto flag = true;               // bool
    
    // 复杂类型的auto推导
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    auto iter = numbers.begin();    // std::vector<int>::iterator
    auto size = numbers.size();     // size_t
    
    std::map<std::string, int> ages = {{"Alice", 25}, {"Bob", 30}};
    auto pair_iter = ages.find("Alice"); // std::map<std::string, int>::iterator
    
    // auto与引用和指针
    auto& ref = integer;            // int&
    auto* ptr = &integer;           // int*
    const auto& const_ref = floating; // const double&
    
    std::cout << "=== 现代auto类型推导 ===" << std::endl;
    std::cout << "integer: " << integer << std::endl;
    std::cout << "floating: " << floating << std::endl;
    std::cout << "vector size: " << size << std::endl;
    
    if (pair_iter != ages.end()) {
        std::cout << "Found: " << pair_iter->first 
                  << " -> " << pair_iter->second << std::endl;
    }
}

int main() {
    traditional_auto_demo();
    std::cout << std::endl;
    modern_auto_demo();
    
    return 0;
}

📊 register存储类

register的使用和废弃

cpp
#include <iostream>

// register存储类(C++17中已废弃)
void register_demo() {
    // 传统register用法(C++17前)
    // register int fast_counter = 0;  // 提示编译器优化
    
    // 现代做法:让编译器自动优化
    int counter = 0;
    
    // 频繁访问的变量,编译器会自动优化
    for (int i = 0; i < 1000000; ++i) {
        counter++;
    }
    
    std::cout << "计数器最终值: " << counter << std::endl;
    
    // register的限制(即使在废弃前):
    // 1. 不能取地址
    // 2. 不能用于数组
    // 3. 只是建议,编译器可以忽略
}

// 现代替代方案:编译器优化
void modern_optimization() {
    // 编译器会自动进行寄存器分配优化
    int frequently_used = 0;
    
    // 使用编译器优化标志:-O2, -O3
    for (int i = 0; i < 10; ++i) {
        frequently_used += i * i;
    }
    
    std::cout << "优化变量值: " << frequently_used << std::endl;
}

int main() {
    register_demo();
    modern_optimization();
    
    return 0;
}

🏛️ static存储类

静态局部变量

cpp
#include <iostream>

// 静态局部变量:在函数调用之间保持值
int get_next_id() {
    static int id_counter = 0;  // 只初始化一次
    return ++id_counter;
}

void demonstrate_static_local() {
    std::cout << "=== 静态局部变量演示 ===" << std::endl;
    
    for (int i = 0; i < 5; ++i) {
        int id = get_next_id();
        std::cout << "生成ID: " << id << std::endl;
    }
}

// 递归函数中的静态变量
long long fibonacci_static(int n) {
    static std::vector<long long> cache;
    
    if (cache.size() <= static_cast<size_t>(n)) {
        cache.resize(n + 1, -1);
    }
    
    if (n <= 1) {
        cache[n] = n;
        return n;
    }
    
    if (cache[n] != -1) {
        return cache[n];  // 使用缓存值
    }
    
    cache[n] = fibonacci_static(n - 1) + fibonacci_static(n - 2);
    return cache[n];
}

void fibonacci_demo() {
    std::cout << "\n=== 斐波那契数列(静态缓存)===" << std::endl;
    
    for (int i = 0; i <= 10; ++i) {
        std::cout << "F(" << i << ") = " << fibonacci_static(i) << std::endl;
    }
}

int main() {
    demonstrate_static_local();
    fibonacci_demo();
    
    return 0;
}

静态全局变量和函数

cpp
#include <iostream>

// 静态全局变量(内部链接,仅在当前文件可见)
static int file_counter = 0;

// 静态函数(内部链接,仅在当前文件可见)
static void increment_file_counter() {
    file_counter++;
    std::cout << "文件计数器: " << file_counter << std::endl;
}

// 普通全局变量(外部链接)
int global_counter = 100;

// 普通全局函数(外部链接)
void increment_global_counter() {
    global_counter++;
    std::cout << "全局计数器: " << global_counter << std::endl;
}

// 静态成员变量和函数
class StaticMemberDemo {
private:
    static int instance_count_;     // 静态成员变量声明
    int instance_id_;
    
public:
    StaticMemberDemo() {
        instance_count_++;
        instance_id_ = instance_count_;
        std::cout << "创建实例 #" << instance_id_ << std::endl;
    }
    
    ~StaticMemberDemo() {
        std::cout << "销毁实例 #" << instance_id_ << std::endl;
    }
    
    // 静态成员函数
    static int getInstanceCount() {
        return instance_count_;
    }
    
    // 静态成员函数:只能访问静态成员
    static void printStaticInfo() {
        std::cout << "当前实例数量: " << instance_count_ << std::endl;
        // std::cout << instance_id_;  // 错误!不能访问非静态成员
    }
    
    int getInstanceId() const {
        return instance_id_;
    }
};

// 静态成员变量定义(必须在类外定义)
int StaticMemberDemo::instance_count_ = 0;

int main() {
    std::cout << "=== 静态全局变量和函数 ===" << std::endl;
    increment_file_counter();
    increment_file_counter();
    increment_global_counter();
    
    std::cout << "\n=== 静态成员演示 ===" << std::endl;
    StaticMemberDemo::printStaticInfo();
    
    {
        StaticMemberDemo obj1, obj2, obj3;
        StaticMemberDemo::printStaticInfo();
    }
    
    StaticMemberDemo::printStaticInfo();
    
    return 0;
}

🌐 extern存储类

外部链接声明

cpp
#include <iostream>

// 声明外部变量(定义在其他文件中)
extern int external_variable;
extern void external_function();

// 在同一文件中的extern使用
int global_var = 42;                // 定义
extern int global_var;              // 声明(可选,因为已在同一文件中定义)

// extern "C" 链接规范
extern "C" {
    // C语言链接,避免C++名称修饰
    void c_function();
    int c_variable;
}

// 函数声明(默认为extern)
void regular_function();           // 等同于 extern void regular_function();

void demonstrate_extern() {
    std::cout << "=== extern存储类演示 ===" << std::endl;
    std::cout << "全局变量: " << global_var << std::endl;
    
    // 如果external_variable在其他文件中定义,可以使用
    // std::cout << "外部变量: " << external_variable << std::endl;
    
    // 调用外部函数
    // external_function();
}

int main() {
    demonstrate_extern();
    return 0;
}

模板特化和extern

cpp
#include <iostream>

// 模板声明
template<typename T>
void template_function(T value) {
    std::cout << "模板函数: " << value << std::endl;
}

// 显式实例化声明(extern template)
extern template void template_function<int>(int);
extern template void template_function<double>(double);

// 在其他编译单元中定义:
// template void template_function<int>(int);
// template void template_function<double>(double);

void template_demo() {
    std::cout << "\n=== 模板extern演示 ===" << std::endl;
    
    // 使用显式实例化的模板
    template_function(42);
    template_function(3.14);
    
    // 隐式实例化
    template_function("Hello");
}

int main() {
    template_demo();
    return 0;
}

🔄 mutable存储类

mutable成员变量

cpp
#include <iostream>
#include <string>

class MutableDemo {
private:
    std::string name_;
    mutable int access_count_;      // mutable成员
    mutable bool cache_valid_;      // mutable缓存标志
    mutable std::string cached_info_; // mutable缓存数据
    
public:
    MutableDemo(const std::string& name) 
        : name_(name), access_count_(0), cache_valid_(false) {}
    
    // const成员函数,但可以修改mutable成员
    const std::string& getName() const {
        access_count_++;            // 修改mutable成员
        return name_;
    }
    
    // const成员函数中的缓存机制
    const std::string& getInfo() const {
        access_count_++;
        
        if (!cache_valid_) {
            // 昂贵的计算过程
            cached_info_ = "Info for " + name_ + " (computed)";
            cache_valid_ = true;
            std::cout << "计算并缓存信息" << std::endl;
        } else {
            std::cout << "使用缓存信息" << std::endl;
        }
        
        return cached_info_;
    }
    
    int getAccessCount() const {
        return access_count_;
    }
    
    // 非const函数会使缓存失效
    void setName(const std::string& new_name) {
        name_ = new_name;
        cache_valid_ = false;       // 清除缓存
    }
};

void mutable_demo() {
    std::cout << "=== mutable存储类演示 ===" << std::endl;
    
    const MutableDemo obj("Alice");
    
    // const对象调用const函数,但mutable成员可以修改
    std::cout << "姓名: " << obj.getName() << std::endl;
    std::cout << "访问次数: " << obj.getAccessCount() << std::endl;
    
    std::cout << "姓名: " << obj.getName() << std::endl;
    std::cout << "访问次数: " << obj.getAccessCount() << std::endl;
    
    // 缓存演示
    std::cout << "\n--- 缓存演示 ---" << std::endl;
    std::cout << obj.getInfo() << std::endl;  // 计算并缓存
    std::cout << obj.getInfo() << std::endl;  // 使用缓存
    
    std::cout << "最终访问次数: " << obj.getAccessCount() << std::endl;
}

int main() {
    mutable_demo();
    return 0;
}

🧵 thread_local存储类 (C++11)

线程局部存储

cpp
#include <iostream>
#include <thread>
#include <vector>

// 线程局部存储变量
thread_local int tls_counter = 0;
thread_local std::string tls_name;

// 线程局部存储函数
void thread_function(int thread_id) {
    // 每个线程都有自己的tls_counter副本
    tls_name = "Thread-" + std::to_string(thread_id);
    
    for (int i = 0; i < 5; ++i) {
        tls_counter++;
        std::cout << tls_name << ": counter = " << tls_counter << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    
    std::cout << tls_name << " final counter: " << tls_counter << std::endl;
}

// 线程局部存储的类成员
class ThreadLocalDemo {
public:
    static thread_local int instance_counter_;
    
    ThreadLocalDemo() {
        instance_counter_++;
        std::cout << "Thread " << std::this_thread::get_id() 
                  << " created instance #" << instance_counter_ << std::endl;
    }
    
    static int getInstanceCount() {
        return instance_counter_;
    }
};

// 静态成员定义
thread_local int ThreadLocalDemo::instance_counter_ = 0;

void class_thread_function(int thread_id) {
    ThreadLocalDemo obj1, obj2;
    std::cout << "Thread " << thread_id 
              << " instance count: " << ThreadLocalDemo::getInstanceCount() << std::endl;
}

void thread_local_demo() {
    std::cout << "=== thread_local存储类演示 ===" << std::endl;
    
    std::vector<std::thread> threads;
    
    // 创建多个线程
    for (int i = 1; i <= 3; ++i) {
        threads.emplace_back(thread_function, i);
    }
    
    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }
    
    std::cout << "\n=== 线程局部类成员演示 ===" << std::endl;
    
    std::vector<std::thread> class_threads;
    for (int i = 1; i <= 2; ++i) {
        class_threads.emplace_back(class_thread_function, i);
    }
    
    for (auto& t : class_threads) {
        t.join();
    }
    
    // 主线程的thread_local变量
    std::cout << "\n主线程 tls_counter: " << tls_counter << std::endl;
    ThreadLocalDemo main_obj;
    std::cout << "主线程实例计数: " << ThreadLocalDemo::getInstanceCount() << std::endl;
}

int main() {
    thread_local_demo();
    return 0;
}

📋 存储类总结

存储类对比表

cpp
#include <iostream>

void storage_class_summary() {
    std::cout << "=== C++存储类总结 ===" << std::endl;
    std::cout << "\n存储类 | 生命周期 | 作用域 | 链接属性 | 主要用途" << std::endl;
    std::cout << "-------|----------|-------|----------|----------" << std::endl;
    std::cout << "auto   | 自动     | 块    | 无       | 类型推导" << std::endl;
    std::cout << "static | 静态     | 局部/文件 | 内部 | 持久化状态" << std::endl;
    std::cout << "extern | 静态     | 全局  | 外部     | 跨文件共享" << std::endl;
    std::cout << "mutable| 对象     | 类    | 无       | const中可变" << std::endl;
    std::cout << "thread_local| 线程 | 线程  | 线程     | 线程安全" << std::endl;
}

// 实际使用建议
void usage_recommendations() {
    std::cout << "\n=== 使用建议 ===" << std::endl;
    
    // 1. 优先使用auto进行类型推导
    auto value = 42;                    // 推荐
    // int value = 42;                  // 传统方式
    
    // 2. 使用static保持函数间状态
    static int call_count = 0;
    call_count++;
    std::cout << "函数调用次数: " << call_count << std::endl;
    
    // 3. 使用extern声明全局变量
    // extern int global_config;       // 在头文件中声明
    
    // 4. 谨慎使用mutable
    // 只在真正需要在const函数中修改成员时使用
    
    // 5. 在多线程程序中使用thread_local
    // thread_local static int thread_counter = 0;
    
    std::cout << "存储类使用建议已展示" << std::endl;
}

int main() {
    storage_class_summary();
    usage_recommendations();
    
    return 0;
}

总结

C++存储类提供了灵活的内存管理和作用域控制机制:

关键存储类

  • auto:现代C++中用于类型推导,大大简化代码
  • static:提供静态存储期,用于保持状态和限制作用域
  • extern:声明外部链接,实现跨文件共享
  • mutable:允许在const函数中修改特定成员
  • thread_local:提供线程安全的局部存储

最佳实践

  • 优先使用auto进行类型推导
  • 合理使用static保持函数间状态
  • 正确使用extern进行模块化设计
  • 谨慎使用mutable,只在必要时使用
  • 在多线程环境中使用thread_local确保线程安全

现代发展

  • register已被废弃,编译器自动优化
  • auto含义已改变,成为类型推导工具
  • thread_local支持现代多线程编程
  • constexpr提供编译时计算能力

理解存储类有助于:

  • 控制变量的生命周期和作用域
  • 实现高效的内存管理
  • 编写模块化和可维护的代码
  • 在多线程环境中确保数据安全

本站内容仅供学习和研究使用。