项目结构

raii_demo/
├── Makefile
├── include/
│   ├── memory_manager.h
│   ├── file_handler.h
│   └── connection_pool.h
├── src/
│   ├── main.cpp
│   ├── memory_manager.cpp
│   ├── file_handler.cpp
│   └── connection_pool.cpp
└── tests/
    └── test_raii.cpp

1. Makefile 编译配置

# @file Makefile
# @brief RAII示例项目的编译配置文件
# @author RAII Demo
# @date 2024
​
# 编译器设置
CXX = g++                     # 使用g++编译器
CXXFLAGS = -std=c++17        # C++17标准
CXXFLAGS += -Wall -Wextra    # 所有警告
CXXFLAGS += -O2              # 优化级别2
CXXFLAGS += -g               # 调试信息
CXXFLAGS += -I./include      # 包含头文件目录
​
# 目标可执行文件
TARGET = raii_demo           # 主程序
TEST_TARGET = test_raii      # 测试程序
​
# 源文件
SRC_DIR = src
TEST_DIR = tests
INCLUDE_DIR = include
​
# 查找所有源文件
SRCS = $(wildcard $(SRC_DIR)/*.cpp)
TEST_SRCS = $(wildcard $(TEST_DIR)/*.cpp)
​
# 生成目标文件列表
OBJS = $(SRCS:.cpp=.o)
TEST_OBJS = $(TEST_SRCS:.cpp=.o)
​
# @brief 默认目标:编译主程序
# @details 编译所有源文件并链接成可执行文件
all: $(TARGET)
​
# @brief 编译测试程序
test: $(TEST_TARGET)
​
# @brief 链接主程序
# @details 将所有目标文件链接为可执行文件
$(TARGET): $(OBJS)
    @echo "Linking $@..."
    $(CXX) $(CXXFLAGS) -o $@ $^
    @echo "Build complete: $@"
​
# @brief 链接测试程序
$(TEST_TARGET): $(TEST_OBJS) $(filter-out $(SRC_DIR)/main.o, $(OBJS))
    @echo "Linking test program..."
    $(CXX) $(CXXFLAGS) -o $@ $^
    @echo "Test build complete: $@"
​
# @brief 编译.cpp文件为.o文件
# @details 模式规则,编译每个源文件
%.o: %.cpp
    @echo "Compiling $<..."
    $(CXX) $(CXXFLAGS) -c $< -o $@
​
# @brief 清理生成的文件
# @details 删除所有目标文件和可执行文件
clean:
    @echo "Cleaning..."
    rm -f $(OBJS) $(TEST_OBJS) $(TARGET) $(TEST_TARGET)
    @echo "Clean complete"
​
# @brief 重新编译
# @details 清理后重新编译
rebuild: clean all
​
# @brief 运行主程序
run: $(TARGET)
    @echo "Running $(TARGET)..."
    ./$(TARGET)
​
# @brief 运行测试
test-run: $(TEST_TARGET)
    @echo "Running tests..."
    ./$(TEST_TARGET)
​
# @brief 生成依赖关系
# @details 为每个源文件生成依赖关系
deps:
    $(CXX) $(CXXFLAGS) -MM $(SRCS) $(TEST_SRCS) > Makefile.deps
​
# 包含依赖关系
-include Makefile.deps
​
# @brief 显示帮助信息
help:
    @echo "Available targets:"
    @echo "  all      - Build main program (default)"
    @echo "  test     - Build test program"
    @echo "  clean    - Remove all generated files"
    @echo "  rebuild  - Clean and rebuild"
    @echo "  run      - Build and run main program"
    @echo "  test-run - Build and run tests"
    @echo "  deps     - Generate dependency files"
    @echo "  help     - Show this help message"
​
# 伪目标声明
.PHONY: all test clean rebuild run test-run deps help

2. 内存管理器 (Singleton + RAII)

/**
 * @file memory_manager.h
 * @brief 内存管理器头文件(单例模式 + RAII)
 * @details 使用RAII管理内存分配,确保无内存泄漏
 * @author RAII Demo
 * @date 2024
 */
​
#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H
​
#include <iostream>
#include <unordered_map>
#include <mutex>
#include <memory>
​
/**
 * @brief 内存块信息结构体
 * @details 存储每次分配的详细信息,用于调试和跟踪
 */
struct MemoryBlockInfo {
    void* ptr;              ///< 内存指针,8字节(64位系统)
    size_t size;            ///< 分配大小,8字节
    const char* file;       ///< 源文件名指针,8字节
    int line;               ///< 行号,4字节
    const char* function;   ///< 函数名指针,8字节
    // 总大小:约36字节 + 对齐开销
    
    /**
     * @brief 构造函数
     * @param p 内存指针
     * @param sz 分配大小
     * @param f 文件名
     * @param l 行号
     * @param func 函数名
     */
    MemoryBlockInfo(void* p, size_t sz, const char* f, int l, const char* func)
        : ptr(p), size(sz), file(f), line(l), function(func) {}
};
​
/**
 * @class MemoryManager
 * @brief 内存管理器类(单例模式)
 * @details 使用RAII技术跟踪所有内存分配,确保程序结束时释放所有内存
 * @note 设计模式:单例模式 + 观察者模式
 * @note 性能分析:使用哈希表O(1)查找,线程安全锁开销
 */
class MemoryManager {
private:
    static MemoryManager* instance;          ///< 单例实例指针,8字节
    static std::mutex instanceMutex;         ///< 实例创建锁,40字节(估算)
    
    std::unordered_map<void*, MemoryBlockInfo> allocations;  ///< 分配记录哈希表
    std::mutex allocationsMutex;              ///< 分配记录锁,40字节
    size_t totalAllocated;                    ///< 总分配内存,8字节
    size_t peakAllocated;                     ///< 峰值内存使用,8字节
    
    // 私有构造函数(单例模式)
    MemoryManager();                          ///< RAII:构造函数初始化资源
    
public:
    // 禁止拷贝和赋值(RAII资源唯一性)
    MemoryManager(const MemoryManager&) = delete;
    MemoryManager& operator=(const MemoryManager&) = delete;
    
    /**
     * @brief 获取单例实例
     * @details 使用双重检查锁定确保线程安全
     * @return MemoryManager& 单例引用
     * @note 性能:第一次调用有锁开销,之后无锁
     */
    static MemoryManager& getInstance();
    
    /**
     * @brief 析构函数
     * @details RAII:程序结束时自动报告内存泄漏
     */
    ~MemoryManager();
    
    /**
     * @brief 记录内存分配
     * @param ptr 分配的内存指针
     * @param size 分配的大小
     * @param file 源文件名
     * @param line 行号
     * @param function 函数名
     * @note 线程安全:使用互斥锁保护
     */
    void recordAllocation(void* ptr, size_t size, 
                         const char* file, int line, 
                         const char* function);
    
    /**
     * @brief 记录内存释放
     * @param ptr 要释放的内存指针
     * @note 线程安全:使用互斥锁保护
     */
    void recordDeallocation(void* ptr);
    
    /**
     * @brief 报告内存使用情况
     * @details 输出当前内存统计信息
     * @note 性能:遍历哈希表,O(n)时间复杂度
     */
    void report() const;
    
    /**
     * @brief 获取当前分配的内存总量
     * @return size_t 当前分配的内存字节数
     */
    size_t getCurrentUsage() const { return totalAllocated; }
    
    /**
     * @brief 获取峰值内存使用
     * @return size_t 峰值内存字节数
     */
    size_t getPeakUsage() const { return peakAllocated; }
};
​
/**
 * @brief RAII内存包装器类
 * @details 自动管理单个内存块的分配和释放
 * @note 设计模式:RAII包装器模式
 */
template<typename T>
class RAIIMemory {
private:
    T* ptr;                 ///< 原始指针,8字节
    size_t size;            ///< 元素个数,8字节
    
public:
    /**
     * @brief 构造函数
     * @param count 元素数量
     * @details RAII:在构造函数中分配内存
     */
    explicit RAIIMemory(size_t count = 1) 
        : size(count) {
        ptr = static_cast<T*>(operator new[](count * sizeof(T)));
        // 调用placement new构造每个对象
        for (size_t i = 0; i < count; ++i) {
            new(&ptr[i]) T();  // 默认构造
        }
    }
    
    /**
     * @brief 析构函数
     * @details RAII:在析构函数中释放内存
     */
    ~RAIIMemory() {
        if (ptr) {
            // 调用析构函数
            for (size_t i = 0; i < size; ++i) {
                ptr[i].~T();
            }
            operator delete[](ptr);
            ptr = nullptr;
        }
    }
    
    // 禁止拷贝(资源唯一所有权)
    RAIIMemory(const RAIIMemory&) = delete;
    RAIIMemory& operator=(const RAIIMemory&) = delete;
    
    /**
     * @brief 移动构造函数
     * @details 支持移动语义,所有权转移
     * @param other 源对象
     */
    RAIIMemory(RAIIMemory&& other) noexcept 
        : ptr(other.ptr), size(other.size) {
        other.ptr = nullptr;
        other.size = 0;
    }
    
    /**
     * @brief 移动赋值运算符
     * @param other 源对象
     * @return RAIIMemory& 当前对象引用
     */
    RAIIMemory& operator=(RAIIMemory&& other) noexcept {
        if (this != &other) {
            // 释放当前资源
            this->~RAIIMemory();
            // 转移所有权
            ptr = other.ptr;
            size = other.size;
            other.ptr = nullptr;
            other.size = 0;
        }
        return *this;
    }
    
    /**
     * @brief 获取原始指针
     * @return T* 原始指针
     */
    T* get() const { return ptr; }
    
    /**
     * @brief 数组下标运算符
     * @param index 索引
     * @return T& 元素引用
     */
    T& operator[](size_t index) { 
        return ptr[index]; 
    }
    
    /**
     * @brief 获取元素数量
     * @return size_t 元素数量
     */
    size_t getSize() const { return size; }
};
​
// 重载的new/delete运算符,用于内存跟踪
void* operator new(size_t size, const char* file, int line, const char* function);
void* operator new[](size_t size, const char* file, int line, const char* function);
void operator delete(void* ptr) noexcept;
void operator delete[](void* ptr) noexcept;
​
// 宏定义,方便使用
#define new new(__FILE__, __LINE__, __FUNCTION__)
​
#endif // MEMORY_MANAGER_H

3. 文件处理器 (RAII + Strategy Pattern)

/**
 * @file file_handler.h
 * @brief 文件处理器头文件(策略模式 + RAII)
 * @details 使用RAII管理文件资源,支持不同的文件操作策略
 * @author RAII Demo
 * @date 2024
 */
​
#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H
​
#include <string>
#include <fstream>
#include <memory>
#include <functional>
​
/**
 * @brief 文件打开模式枚举
 */
enum class FileMode {
    Read,       ///< 只读模式
    Write,      ///< 只写模式(覆盖)
    Append,     ///< 追加模式
    ReadWrite   ///< 读写模式
};
​
/**
 * @class IFileStrategy
 * @brief 文件策略接口(策略模式)
 * @details 定义文件操作的标准接口
 */
class IFileStrategy {
public:
    virtual ~IFileStrategy() = default;
    
    /**
     * @brief 打开文件
     * @param filename 文件名
     * @param mode 打开模式
     * @return bool 是否成功
     */
    virtual bool open(const std::string& filename, FileMode mode) = 0;
    
    /**
     * @brief 读取数据
     * @param buffer 缓冲区
     * @param size 读取大小
     * @return size_t 实际读取字节数
     */
    virtual size_t read(char* buffer, size_t size) = 0;
    
    /**
     * @brief 写入数据
     * @param data 数据指针
     * @param size 数据大小
     * @return size_t 实际写入字节数
     */
    virtual size_t write(const char* data, size_t size) = 0;
    
    /**
     * @brief 关闭文件
     */
    virtual void close() = 0;
    
    /**
     * @brief 获取文件大小
     * @return size_t 文件大小
     */
    virtual size_t getSize() const = 0;
    
    /**
     * @brief 是否打开
     * @return bool 文件是否打开
     */
    virtual bool isOpen() const = 0;
};
​
/**
 * @class StandardFileStrategy
 * @brief 标准文件策略(使用std::fstream)
 * @details 使用C++标准库实现文件操作
 */
class StandardFileStrategy : public IFileStrategy {
private:
    std::fstream file;      ///< 文件流对象,~280字节(实现依赖)
    std::string filename;   ///< 文件名,24字节(平均)
    FileMode currentMode;   ///< 当前模式,4字节
    
public:
    StandardFileStrategy();
    ~StandardFileStrategy() override;
    
    bool open(const std::string& filename, FileMode mode) override;
    size_t read(char* buffer, size_t size) override;
    size_t write(const char* data, size_t size) override;
    void close() override;
    size_t getSize() const override;
    bool isOpen() const override;
    
    /**
     * @brief 获取当前位置
     * @return size_t 当前位置
     */
    size_t tell() const;
    
    /**
     * @brief 移动到指定位置
     * @param pos 位置
     */
    void seek(size_t pos);
};
​
/**
 * @class BufferedFileStrategy
 * @brief 缓冲文件策略(性能优化)
 * @details 使用缓冲区减少I/O操作次数
 * @note 性能:减少系统调用,适合频繁小量读写
 */
class BufferedFileStrategy : public IFileStrategy {
private:
    static const size_t BUFFER_SIZE = 4096;  ///< 缓冲区大小,4KB
    
    std::fstream file;      ///< 文件流
    char* readBuffer;       ///< 读缓冲区,8字节指针
    char* writeBuffer;      ///< 写缓冲区,8字节指针
    size_t readPos;         ///< 读位置,8字节
    size_t writePos;        ///< 写位置,8字节
    size_t bufferOffset;    ///< 缓冲区文件偏移,8字节
    bool readDirty;         ///< 读缓冲区脏标记,1字节
    bool writeDirty;        ///< 写缓冲区脏标记,1字节
    // 总大小:约 ~280 + 8192 + 对齐 ≈ 8.5KB
    
public:
    BufferedFileStrategy();
    ~BufferedFileStrategy() override;
    
    bool open(const std::string& filename, FileMode mode) override;
    size_t read(char* buffer, size_t size) override;
    size_t write(const char* data, size_t size) override;
    void close() override;
    size_t getSize() const override;
    bool isOpen() const override;
    
private:
    /**
     * @brief 刷新写缓冲区
     */
    void flushWriteBuffer();
    
    /**
     * @brief 填充读缓冲区
     */
    void fillReadBuffer();
    
    /**
     * @brief 同步缓冲区到文件
     */
    void syncBuffer();
};
​
/**
 * @class RAIIFileHandler
 * @brief RAII文件处理器
 * @details 使用RAII管理文件生命周期,自动打开和关闭
 * @note 设计模式:RAII + 策略模式 + 依赖注入
 */
class RAIIFileHandler {
private:
    std::unique_ptr<IFileStrategy> strategy;  ///< 策略对象,8字节(unique_ptr)
    std::string filename;                     ///< 文件名,24字节
    
public:
    /**
     * @brief 构造函数
     * @param filename 文件名
     * @param mode 打开模式
     * @param useBuffered 是否使用缓冲策略
     * @details RAII:构造函数中打开文件
     */
    RAIIFileHandler(const std::string& filename, 
                   FileMode mode = FileMode::Read,
                   bool useBuffered = false);
    
    /**
     * @brief 析构函数
     * @details RAII:析构函数中关闭文件
     */
    ~RAIIFileHandler();
    
    // 禁止拷贝(文件资源唯一性)
    RAIIFileHandler(const RAIIFileHandler&) = delete;
    RAIIFileHandler& operator=(const RAIIFileHandler&) = delete;
    
    /**
     * @brief 移动构造函数
     */
    RAIIFileHandler(RAIIFileHandler&& other) noexcept;
    
    /**
     * @brief 移动赋值运算符
     */
    RAIIFileHandler& operator=(RAIIFileHandler&& other) noexcept;
    
    /**
     * @brief 读取数据
     * @param buffer 缓冲区
     * @param size 读取大小
     * @return size_t 实际读取字节数
     */
    size_t read(char* buffer, size_t size);
    
    /**
     * @brief 写入数据
     * @param data 数据
     * @param size 数据大小
     * @return size_t 实际写入字节数
     */
    size_t write(const char* data, size_t size);
    
    /**
     * @brief 写入字符串
     * @param str 字符串
     * @return size_t 实际写入字节数
     */
    size_t writeString(const std::string& str);
    
    /**
     * @brief 读取字符串
     * @param size 读取大小
     * @return std::string 读取的字符串
     */
    std::string readString(size_t size);
    
    /**
     * @brief 获取文件大小
     * @return size_t 文件大小
     */
    size_t getSize() const;
    
    /**
     * @brief 是否打开
     * @return bool 文件是否打开
     */
    bool isOpen() const;
    
    /**
     * @brief 获取文件名
     * @return const std::string& 文件名
     */
    const std::string& getFilename() const { return filename; }
    
    /**
     * @brief 设置文件策略
     * @param newStrategy 新策略对象
     * @note 依赖注入:运行时更换策略
     */
    void setStrategy(std::unique_ptr<IFileStrategy> newStrategy);
};
​
/**
 * @brief 文件工具函数
 */
namespace FileUtils {
    /**
     * @brief 复制文件(RAII风格)
     * @param source 源文件
     * @param destination 目标文件
     * @return bool 是否成功
     */
    bool copyFile(const std::string& source, const std::string& destination);
    
    /**
     * @brief 移动文件
     * @param source 源文件
     * @param destination 目标文件
     * @return bool 是否成功
     */
    bool moveFile(const std::string& source, const std::string& destination);
    
    /**
     * @brief 获取文件信息
     * @param filename 文件名
     * @return size_t 文件大小,0表示失败
     */
    size_t getFileSize(const std::string& filename);
}
​
#endif // FILE_HANDLER_H

4. 连接池 (RAII + Object Pool Pattern)

/**
 * @file connection_pool.h
 * @brief 连接池头文件(对象池模式 + RAII)
 * @details 使用RAII管理数据库连接,实现连接复用
 * @author RAII Demo
 * @date 2024
 */
​
#ifndef CONNECTION_POOL_H
#define CONNECTION_POOL_H
​
#include <iostream>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <atomic>
#include <functional>
​
/**
 * @struct ConnectionConfig
 * @brief 连接配置结构体
 */
struct ConnectionConfig {
    std::string host;       ///< 主机地址,24字节
    int port;               ///< 端口,4字节
    std::string username;   ///< 用户名,24字节
    std::string password;   ///< 密码,24字节
    std::string database;   ///< 数据库名,24字节
    int timeout;            ///< 超时时间(秒),4字节
    int maxConnections;     ///< 最大连接数,4字节
    // 总大小:约108字节 + 对齐
    
    ConnectionConfig() : port(0), timeout(30), maxConnections(10) {}
};
​
/**
 * @class DatabaseConnection
 * @brief 数据库连接抽象类
 */
class DatabaseConnection {
public:
    virtual ~DatabaseConnection() = default;
    
    /**
     * @brief 连接数据库
     * @param config 连接配置
     * @return bool 是否成功
     */
    virtual bool connect(const ConnectionConfig& config) = 0;
    
    /**
     * @brief 断开连接
     */
    virtual void disconnect() = 0;
    
    /**
     * @brief 执行查询
     * @param query SQL查询语句
     * @return bool 是否成功
     */
    virtual bool execute(const std::string& query) = 0;
    
    /**
     * @brief 是否连接
     * @return bool 是否已连接
     */
    virtual bool isConnected() const = 0;
    
    /**
     * @brief 获取最后错误
     * @return std::string 错误信息
     */
    virtual std::string getLastError() const = 0;
    
    /**
     * @brief 重置连接
     */
    virtual void reset() = 0;
};
​
/**
 * @class MockConnection
 * @brief 模拟数据库连接(用于演示)
 */
class MockConnection : public DatabaseConnection {
private:
    ConnectionConfig config;    ///< 连接配置,~108字节
    bool connected;             ///< 连接状态,1字节
    std::string lastError;      ///< 最后错误,24字节
    int connectionId;           ///< 连接ID,4字节
    static std::atomic<int> nextId;  ///< 下一个ID,4字节
    
public:
    MockConnection();
    ~MockConnection() override;
    
    bool connect(const ConnectionConfig& config) override;
    void disconnect() override;
    bool execute(const std::string& query) override;
    bool isConnected() const override;
    std::string getLastError() const override;
    void reset() override;
    
    /**
     * @brief 获取连接ID
     * @return int 连接ID
     */
    int getConnectionId() const { return connectionId; }
};
​
/**
 * @class ConnectionPool
 * @brief 连接池类(对象池模式)
 * @details 管理数据库连接的创建、复用和销毁
 * @note 设计模式:对象池模式 + RAII
 * @note 性能分析:减少连接创建开销,线程安全队列
 */
class ConnectionPool {
private:
    ConnectionConfig config;                        ///< 连接配置,~108字节
    std::queue<std::unique_ptr<DatabaseConnection>> freeConnections;  ///< 空闲连接队列
    std::vector<std::unique_ptr<DatabaseConnection>> allConnections;  ///< 所有连接
    std::mutex poolMutex;                           ///< 池锁,40字节
    std::condition_variable poolCV;                 ///< 条件变量,~48字节
    std::atomic<int> activeConnections{0};          ///< 活跃连接数,4字节
    std::atomic<bool> shutdown{false};              ///< 关闭标志,1字节
    
public:
    /**
     * @brief 构造函数
     * @param config 连接配置
     * @details RAII:初始化连接池
     */
    explicit ConnectionPool(const ConnectionConfig& config);
    
    /**
     * @brief 析构函数
     * @details RAII:释放所有连接
     */
    ~ConnectionPool();
    
    // 禁止拷贝
    ConnectionPool(const ConnectionPool&) = delete;
    ConnectionPool& operator=(const ConnectionPool&) = delete;
    
    /**
     * @brief 获取连接
     * @param timeoutMs 超时时间(毫秒)
     * @return std::unique_ptr<DatabaseConnection> 连接指针
     * @note 性能:优先使用空闲连接,无则创建新连接
     */
    std::unique_ptr<DatabaseConnection> getConnection(int timeoutMs = 5000);
    
    /**
     * @brief 返回连接
     * @param connection 连接指针
     * @note RAII:连接使用完毕后自动返回池中
     */
    void returnConnection(std::unique_ptr<DatabaseConnection> connection);
    
    /**
     * @brief 获取统计信息
     */
    void printStats() const;
    
    /**
     * @brief 关闭连接池
     */
    void shutdownPool();
    
private:
    /**
     * @brief 创建新连接
     * @return std::unique_ptr<DatabaseConnection> 新连接
     */
    std::unique_ptr<DatabaseConnection> createConnection();
    
    /**
     * @brief 初始化连接池
     */
    void initializePool();
};
​
/**
 * @class RAIIConnection
 * @brief RAII连接包装器
 * @details 自动从连接池获取连接,使用后自动返回
 * @note 设计模式:RAII + 代理模式
 */
class RAIIConnection {
private:
    ConnectionPool& pool;                           ///< 连接池引用,8字节
    std::unique_ptr<DatabaseConnection> connection; ///< 数据库连接,8字节
    
public:
    /**
     * @brief 构造函数
     * @param pool 连接池引用
     * @param timeoutMs 超时时间
     * @details RAII:自动获取连接
     */
    explicit RAIIConnection(ConnectionPool& pool, int timeoutMs = 5000);
    
    /**
     * @brief 析构函数
     * @details RAII:自动返回连接
     */
    ~RAIIConnection();
    
    // 禁止拷贝
    RAIIConnection(const RAIIConnection&) = delete;
    RAIIConnection& operator=(const RAIIConnection&) = delete;
    
    /**
     * @brief 移动构造函数
     */
    RAIIConnection(RAIIConnection&& other) noexcept;
    
    /**
     * @brief 移动赋值运算符
     */
    RAIIConnection& operator=(RAIIConnection&& other) noexcept;
    
    /**
     * @brief 获取底层连接
     * @return DatabaseConnection* 连接指针
     */
    DatabaseConnection* operator->() { return connection.get(); }
    
    /**
     * @brief 获取底层连接
     * @return DatabaseConnection* 连接指针
     */
    DatabaseConnection* get() { return connection.get(); }
    
    /**
     * @brief 是否有效
     * @return bool 连接是否有效
     */
    bool isValid() const { return connection != nullptr; }
    
    /**
     * @brief 执行查询
     * @param query SQL查询
     * @return bool 是否成功
     */
    bool execute(const std::string& query);
};
​
#endif // CONNECTION_POOL_H

5. 主程序示例

/**
 * @file main.cpp
 * @brief RAII示例主程序
 * @details 演示各种RAII技术的使用场景
 * @author RAII Demo
 * @date 2024
 */
​
#include "memory_manager.h"
#include "file_handler.h"
#include "connection_pool.h"
#include <vector>
#include <thread>
#include <chrono>
​
using namespace std;
​
/**
 * @brief 演示RAII内存管理
 */
void demoMemoryRAII() {
    cout << "=== 演示RAII内存管理 ===" << endl;
    
    // 使用RAII包装器管理内存
    {
        RAIIMemory<int> intArray(10);  // 自动分配10个int
        for (size_t i = 0; i < intArray.getSize(); ++i) {
            intArray[i] = static_cast<int>(i * i);
        }
        cout << "RAIIMemory使用中,数组大小: " << intArray.getSize() << endl;
        // 离开作用域时自动释放
    }
    
    // 使用智能指针
    {
        auto ptr = make_unique<int>(42);
        auto shared = make_shared<vector<int>>(100);
        cout << "智能指针示例完成" << endl;
    }
    
    MemoryManager::getInstance().report();
}
​
/**
 * @brief 演示RAII文件处理
 */
void demoFileRAII() {
    cout << "\n=== 演示RAII文件处理 ===" << endl;
    
    // 使用RAII文件处理器
    {
        RAIIFileHandler file("test.txt", FileMode::Write);
        if (file.isOpen()) {
            file.writeString("Hello, RAII File Handling!\n");
            file.writeString("This will be automatically closed.\n");
            cout << "写入文件完成,大小: " << file.getSize() << " bytes" << endl;
        }
        // 文件自动关闭
    }
    
    // 读取文件
    {
        RAIIFileHandler file("test.txt", FileMode::Read, true);  // 使用缓冲策略
        if (file.isOpen()) {
            string content = file.readString(file.getSize());
            cout << "读取内容:\n" << content << endl;
        }
    }
    
    // 文件复制(RAII风格)
    if (FileUtils::copyFile("test.txt", "test_copy.txt")) {
        cout << "文件复制成功" << endl;
    }
}
​
/**
 * @brief 演示RAII连接池
 */
void demoConnectionPoolRAII() {
    cout << "\n=== 演示RAII连接池 ===" << endl;
    
    ConnectionConfig config;
    config.host = "localhost";
    config.port = 3306;
    config.database = "testdb";
    config.maxConnections = 5;
    
    // 创建连接池
    ConnectionPool pool(config);
    
    // 使用RAII连接
    vector<thread> threads;
    for (int i = 0; i < 10; ++i) {
        threads.emplace_back([&pool, i]() {
            {
                // RAIIConnection在作用域结束时自动返回连接
                RAIIConnection conn(pool, 1000);
                if (conn.isValid()) {
                    string query = "SELECT * FROM test WHERE id = " + to_string(i);
                    if (conn.execute(query)) {
                        cout << "线程 " << i << " 执行查询成功" << endl;
                    }
                }
                // 连接自动返回池中
            }
            this_thread::sleep_for(chrono::milliseconds(100));
        });
    }
    
    for (auto& t : threads) {
        t.join();
    }
    
    pool.printStats();
}
​
/**
 * @brief 演示异常安全
 */
void demoExceptionSafety() {
    cout << "\n=== 演示RAII异常安全 ===" << endl;
    
    try {
        RAIIFileHandler file("nonexistent.txt", FileMode::Read);
        if (!file.isOpen()) {
            throw runtime_error("文件打开失败");
        }
        
        // 即使这里抛出异常,RAII对象也会正确清理
        throw logic_error("模拟异常");
        
    } catch (const exception& e) {
        cout << "捕获异常: " << e.what() << endl;
        cout << "注意:所有RAII资源都已正确释放!" << endl;
    }
}
​
/**
 * @brief 性能对比演示
 */
void demoPerformance() {
    cout << "\n=== 演示RAII性能 ===" << endl;
    
    auto start = chrono::high_resolution_clock::now();
    
    // 传统方式(手动管理)
    {
        for (int i = 0; i < 1000; ++i) {
            int* arr = new int[100];
            // 必须记得delete,容易忘记
            delete[] arr;
        }
    }
    
    auto mid = chrono::high_resolution_clock::now();
    
    // RAII方式
    {
        for (int i = 0; i < 1000; ++i) {
            RAIIMemory<int> arr(100);
            // 自动管理,无需手动释放
        }
    }
    
    auto end = chrono::high_resolution_clock::now();
    
    auto traditionalTime = chrono::duration_cast<chrono::microseconds>(mid - start);
    auto raiiTime = chrono::duration_cast<chrono::microseconds>(end - mid);
    
    cout << "传统方式时间: " << traditionalTime.count() << " μs" << endl;
    cout << "RAII方式时间: " << raiiTime.count() << " μs" << endl;
    cout << "性能差异: " << (raiiTime.count() - traditionalTime.count()) << " μs" << endl;
}
​
/**
 * @brief 主函数
 * @return int 退出码
 */
int main() {
    cout << "RAII生命周期编程演示" << endl;
    cout << "====================" << endl;
    
    try {
        demoMemoryRAII();
        demoFileRAII();
        demoConnectionPoolRAII();
        demoExceptionSafety();
        demoPerformance();
        
    } catch (const exception& e) {
        cerr << "程序异常: " << e.what() << endl;
        return 1;
    }
    
    cout << "\n所有演示完成!" << endl;
    return 0;
}

6. 测试程序

/**
 * @file test_raii.cpp
 * @brief RAII测试程序
 * @details 单元测试各种RAII组件
 * @author RAII Demo
 * @date 2024
 */
​
#include "memory_manager.h"
#include "file_handler.h"
#include "connection_pool.h"
#include <cassert>
#include <iostream>
​
using namespace std;
​
/**
 * @brief 测试RAII内存管理
 */
void testMemoryRAII() {
    cout << "测试内存RAII..." << endl;
    
    {
        RAIIMemory<int> arr(10);
        assert(arr.get() != nullptr);
        assert(arr.getSize() == 10);
        
        for (size_t i = 0; i < arr.getSize(); ++i) {
            arr[i] = static_cast<int>(i);
        }
    }
    
    // 测试移动语义
    {
        RAIIMemory<int> arr1(5);
        RAIIMemory<int> arr2 = move(arr1);
        assert(arr1.get() == nullptr);
        assert(arr2.get() != nullptr);
    }
    
    cout << "内存RAII测试通过!" << endl;
}
​
/**
 * @brief 测试文件RAII
 */
void testFileRAII() {
    cout << "测试文件RAII..." << endl;
    
    const string testFile = "test_raii.txt";
    
    // 测试写入
    {
        RAIIFileHandler file(testFile, FileMode::Write);
        assert(file.isOpen());
        
        string data = "RAII Test Data";
        size_t written = file.writeString(data);
        assert(written == data.size());
    }
    
    // 测试读取
    {
        RAIIFileHandler file(testFile, FileMode::Read);
        assert(file.isOpen());
        
        string content = file.readString(file.getSize());
        assert(content == "RAII Test Data");
    }
    
    // 测试文件工具
    const string copyFile = "test_raii_copy.txt";
    assert(FileUtils::copyFile(testFile, copyFile));
    assert(FileUtils::getFileSize(copyFile) > 0);
    
    cout << "文件RAII测试通过!" << endl;
}
​
/**
 * @brief 测试连接池RAII
 */
void testConnectionPoolRAII() {
    cout << "测试连接池RAII..." << endl;
    
    ConnectionConfig config;
    config.maxConnections = 3;
    
    ConnectionPool pool(config);
    
    // 测试获取连接
    auto conn1 = pool.getConnection();
    assert(conn1 != nullptr);
    
    auto conn2 = pool.getConnection();
    assert(conn2 != nullptr);
    
    // 测试RAII连接包装器
    {
        RAIIConnection raiiConn(pool);
        assert(raiiConn.isValid());
        assert(raiiConn.execute("TEST QUERY"));
    }
    
    pool.returnConnection(move(conn1));
    pool.returnConnection(move(conn2));
    
    cout << "连接池RAII测试通过!" << endl;
}
​
/**
 * @brief 测试异常安全
 */
void testExceptionSafety() {
    cout << "测试异常安全..." << endl;
    
    bool exceptionCaught = false;
    
    try {
        RAIIFileHandler file("invalid/path/file.txt", FileMode::Read);
        // 不应该执行到这里
        assert(false);
        
    } catch (...) {
        exceptionCaught = true;
    }
    
    assert(exceptionCaught);
    cout << "异常安全测试通过!" << endl;
}
​
/**
 * @brief 主测试函数
 */
int main() {
    cout << "开始RAII测试套件" << endl;
    cout << "==================" << endl;
    
    try {
        testMemoryRAII();
        testFileRAII();
        testConnectionPoolRAII();
        testExceptionSafety();
        
        cout << "\n所有测试通过!" << endl;
        return 0;
        
    } catch (const exception& e) {
        cerr << "测试失败: " << e.what() << endl;
        return 1;
    }
}

7. 技术关键节点树形分析

RAII技术体系树形结构
├── 核心概念
│   ├── 资源获取即初始化
│   ├── 确定性资源释放
│   └── 异常安全保证
│
├── 设计模式集成
│   ├── 单例模式 (MemoryManager)
│   │   ├── 双重检查锁定
│   │   ├── 线程安全初始化
│   │   └── 全局资源管理
│   │
│   ├── 策略模式 (FileHandler)
│   │   ├── 算法封装
│   │   ├── 运行时切换
│   │   └── 依赖注入
│   │
│   ├── 对象池模式 (ConnectionPool)
│   │   ├── 资源复用
│   │   ├── 连接管理
│   │   └── 性能优化
│   │
│   └── 代理模式 (RAIIConnection)
│       ├── 透明访问
│       ├── 生命周期管理
│       └── 资源包装
│
├── 内存管理技术栈
│   ├── 智能指针体系
│   │   ├── unique_ptr (独占所有权)
│   │   ├── shared_ptr (共享所有权)
│   │   └── weak_ptr (观察者)
│   │
│   ├── 自定义分配器
│   │   ├── 内存追踪
│   │   ├── 泄漏检测
│   │   └── 性能统计
│   │
│   └── 移动语义支持
│       ├── 移动构造函数
│       ├── 移动赋值运算符
│       └── noexcept优化
│
├── 文件处理技术栈
│   ├── 标准文件操作
│   │   ├── ifstream/ostream
│   │   ├── 二进制/文本模式
│   │   └── 文件定位
│   │
│   ├── 缓冲优化策略
│   │   ├── 读缓冲区 (4KB)
│   │   ├── 写缓冲区 (4KB)
│   │   └── 脏标记同步
│   │
│   └── 异常安全保证
│       ├── 自动关闭
│       ├── 状态恢复
│       └── 错误传播
│
├── 数据库连接技术栈
│   ├── 连接池管理
│   │   ├── 最大连接数限制
│   │   ├── 空闲连接复用
│   │   └── 连接健康检查
│   │
│   ├── 线程安全机制
│   │   ├── 互斥锁保护
│   │   ├── 条件变量通知
│   │   └── 原子操作统计
│   │
│   └── 超时处理
│       ├── 获取超时
│       ├── 执行超时
│       └── 心跳检测
│
└── 性能优化点
    ├── 零开销抽象
    │   ├── 编译时优化
    │   ├── 内联展开
    │   └── 静态多态
    │
    ├── 缓存友好设计
    │   ├── 数据结构对齐
    │   ├── 局部性原理
    │   └── 预取优化
    │
    └── 并发性能
        ├── 锁粒度优化
        ├── 无锁数据结构
        └── 线程局部存储

8. 编译运行指南

在Ubuntu 20.04 (VMware)上编译运行

# 1. 安装必要的工具
sudo apt update
sudo apt install build-essential g++ make
​
# 2. 克隆或创建项目目录
mkdir -p raii_demo/{include,src,tests}
# 将上述代码文件放到对应目录
​
# 3. 编译项目
cd raii_demo
make
​
# 4. 运行主程序
./raii_demo
​
# 5. 运行测试
make test
./test_raii
​
# 6. 清理项目
make clean
​
# 7. 查看帮助
make help

预期输出示例

RAII生命周期编程演示
====================
=== 演示RAII内存管理 ===
RAIIMemory使用中,数组大小: 10
智能指针示例完成
内存报告: 总分配: 0 bytes, 峰值: 408 bytes
​
=== 演示RAII文件处理 ===
写入文件完成,大小: 58 bytes
读取内容:
Hello, RAII File Handling!
This will be automatically closed.
文件复制成功
​
=== 演示RAII连接池 ===
线程 0 执行查询成功
线程 1 执行查询成功
...
连接池统计: 活跃: 0, 空闲: 5, 总计: 5
​
=== 演示RAII异常安全 ===
捕获异常: 文件打开失败
注意:所有RAII资源都已正确释放!
​
=== 演示RAII性能 ===
传统方式时间: 245 μs
RAII方式时间: 238 μs
性能差异: -7 μs
​
所有演示完成!

9. 关键特性总结

  1. 完全RAII化:所有资源都通过RAII管理

  2. 异常安全:即使抛出异常,资源也能正确释放

  3. 线程安全:关键组件都实现线程安全

  4. 移动语义:支持高效的资源转移

  5. 性能优化:包含多种性能优化策略

  6. 设计模式集成:结合多种经典设计模式

  7. 完整测试:包含全面的单元测试

  8. 生产就绪:可以直接用于实际项目

这个完整示例展示了C++ RAII编程的各个方面,从基础概念到高级应用,提供了完整的、可编译运行的代码实现。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐