C/C++实战项目精选:从入门到精通的100个经典案例

C/C++实战项目精选:从入门到精通的100个经典案例

本文精选了四个高质量的C/C++实战项目,涵盖STL库实现、网络服务器开发、智能指针内存管理和数据库连接池高并发架构。通过MyTinySTL项目深入理解STL内部机制;TinyWebServer展示高性能网络编程;智能指针项目解析现代C++内存管理;数据库连接池项目探讨高并发架构设计。这些项目从基础到高级,帮助开发者系统掌握C++核心技术和工程实践。

MyTinySTL:手写STL库的最佳实践

在C++开发者的成长道路上,手写一个简化版的STL(Standard Template Library)库是一个极具价值的练习项目。MyTinySTL作为基于C++11的轻量级STL实现,不仅帮助开发者深入理解STL的内部机制,更是掌握现代C++编程技巧的绝佳途径。

项目概述与设计理念

MyTinySTL项目采用了模块化的设计思想,将STL的各个组件进行精心拆分和实现。整个项目结构清晰,代码风格统一,注释详细,特别适合初学者学习和参考。

mermaid

核心容器实现详解

vector容器的实现

vector作为最常用的序列容器,其实现涉及到动态内存管理、迭代器设计、异常安全等多个重要概念。MyTinySTL中的vector实现展示了如何高效地处理内存分配和元素操作。

template <typename T>
class vector {
public:
    // 类型定义
    typedef T value_type;
    typedef T* pointer;
    typedef T* iterator;
    typedef const T* const_iterator;
    typedef size_t size_type;
    
    // 构造函数
    vector() : start_(nullptr), finish_(nullptr), end_of_storage_(nullptr) {}
    
    explicit vector(size_type n) {
        start_ = data_allocator::allocate(n);
        finish_ = start_ + n;
        end_of_storage_ = finish_;
        mystl::uninitialized_fill_n(start_, n, value_type());
    }
    
    // 容量相关操作
    size_type size() const { return finish_ - start_; }
    size_type capacity() const { return end_of_storage_ - start_; }
    bool empty() const { return start_ == finish_; }
    
    // 元素访问
    reference operator[](size_type n) { return *(start_ + n); }
    const_reference operator[](size_type n) const { return *(start_ + n); }
    
    // 内存管理
    void reserve(size_type new_cap);
    void resize(size_type new_size, const value_type& value = value_type());
    
private:
    iterator start_;           // 指向首元素
    iterator finish_;          // 指向最后一个元素的下一个位置
    iterator end_of_storage_;  // 指向存储空间末尾
};
内存分配策略

MyTinySTL采用了自定义的内存分配器,实现了更高效的内存管理。通过内存池技术和对象构造分离,显著提升了容器性能。

template <typename T>
class allocator {
public:
    static T* allocate(size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }
    
    static void deallocate(T* p, size_t n) {
        ::operator delete(p);
    }
    
    static void construct(T* p, const T& value) {
        new (p) T(value);  // placement new
    }
    
    static void destroy(T* p) {
        p->~T();
    }
};

迭代器设计与实现

迭代器是STL的核心抽象,MyTinySTL实现了完整的迭代器体系,包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器。

mermaid

算法库的实现技巧

MyTinySTL算法库实现了STL中常用的算法,如排序、查找、数值操作等。这些算法的实现充分展示了模板元编程和泛型编程的强大能力。

快速排序算法实现
template <typename RandomAccessIterator>
void quick_sort(RandomAccessIterator first, RandomAccessIterator last) {
    if (first != last) {
        auto pivot = *first;
        auto left = first;
        auto right = last - 1;
        
        while (left < right) {
            while (left < right && *right >= pivot) --right;
            *left = *right;
            
            while (left < right && *left <= pivot) ++left;
            *right = *left;
        }
        
        *left = pivot;
        quick_sort(first, left);
        quick_sort(left + 1, last);
    }
}

// 使用SFINAE技术进行算法优化
template <typename Iterator>
typename std::enable_if<
    std::is_same<
        typename std::iterator_traits<Iterator>::iterator_category,
        std::random_access_iterator_tag
    >::value
>::type
sort(Iterator first, Iterator last) {
    quick_sort(first, last);
}

异常安全保证

MyTinySTL在实现过程中严格遵守异常安全原则,确保在异常发生时资源不会泄漏,程序状态保持一致。

异常安全级别描述实现要求
基本保证程序状态保持有效,无资源泄漏所有操作都满足
强保证操作要么成功,要么回滚到操作前状态关键操作满足
不抛异常保证操作保证不会抛出异常特定函数满足

性能优化策略

MyTinySTL在性能优化方面做了大量工作,主要包括:

  1. 内联函数优化:对小型函数进行内联处理
  2. 移动语义支持:充分利用C++11的移动语义
  3. 内存池技术:减少内存分配开销
  4. 算法选择:根据数据特征选择最优算法
// 移动构造函数示例
template <typename T>
vector<T>::vector(vector&& other) noexcept
    : start_(other.start_),
      finish_(other.finish_),
      end_of_storage_(other.end_of_storage_) {
    other.start_ = other.finish_ = other.end_of_storage_ = nullptr;
}

测试与验证体系

一个完整的STL实现需要完善的测试体系。MyTinySTL包含了全面的单元测试和性能测试,确保实现的正确性和高效性。

// 单元测试示例
TEST(vector_test, push_back_test) {
    mystl::vector<int> v;
    for (int i = 0; i < 100; ++i) {
        v.push_back(i);
        EXPECT_EQ(v[i], i);
        EXPECT_EQ(v.size(), i + 1);
    }
}

TEST(vector_test, iterator_test) {
    mystl::vector<int> v = {1, 2, 3, 4, 5};
    int sum = 0;
    for (auto it = v.begin(); it != v.end(); ++it) {
        sum += *it;
    }
    EXPECT_EQ(sum, 15);
}

开发最佳实践总结

通过分析MyTinySTL的实现,我们可以总结出以下最佳实践:

  1. 模块化设计:将功能分解为独立的模块
  2. 接口一致性:保持与标准STL相同的接口
  3. 异常安全:确保资源管理的安全性
  4. 性能优化:在保证正确性的前提下进行优化
  5. 完整测试:建立全面的测试体系

学习价值与应用场景

MyTinySTL不仅是一个学习项目,其设计思想和实现技巧在实际开发中也有广泛应用:

  • 嵌入式开发:轻量级的STL实现适合资源受限环境
  • 教学示范:优秀的代码规范和注释适合教学使用
  • 性能敏感场景:自定义内存分配器可优化特定场景性能
  • 跨平台开发:不依赖特定平台的标准库实现

通过深入研究和实践MyTinySTL,开发者能够全面提升对C++语言特性、模板编程、内存管理、算法设计等核心技术的理解,为成为高级C++工程师奠定坚实基础。

TinyWebServer:轻量级网络服务器开发

在当今互联网时代,网络服务器是支撑各种Web应用的核心基础设施。TinyWebServer作为一个用C++实现的轻量级Web服务器项目,不仅展示了高性能服务器编程的精髓,更为初学者提供了一个绝佳的学习平台。本文将深入探讨TinyWebServer的核心架构、关键技术实现以及开发实践。

项目概述与技术架构

TinyWebServer采用了现代化的服务器设计模式,集成了多种高性能编程技术,构建了一个完整的B/S模型Web服务器。其核心架构基于以下技术组合:

核心技术栈:

  • 线程池 + 非阻塞socket:实现高效的并发处理
  • epoll(ET和LT模式):提供高性能的I/O多路复用
  • 事件处理模型:支持Reactor和模拟Proactor两种模式
  • 状态机解析:用于HTTP请求报文解析
  • 数据库连接池:优化数据库访问性能
  • 同步/异步日志系统:记录服务器运行状态

mermaid

核心模块详解

1. 线程同步机制封装类

TinyWebServer通过封装类实现了线程安全的同步机制,确保多线程环境下的数据一致性:

class Locker {
public:
    Locker() {
        if (pthread_mutex_init(&m_mutex, NULL) != 0) {
            throw std::exception();
        }
    }
    ~Locker() {
        pthread_mutex_destroy(&m_mutex);
    }
    bool lock() {
        return pthread_mutex_lock(&m_mutex) == 0;
    }
    bool unlock() {
        return pthread_mutex_unlock(&m_mutex) == 0;
    }
    pthread_mutex_t* get() {
        return &m_mutex;
    }

private:
    pthread_mutex_t m_mutex;
};
2. 半同步/半反应堆线程池

线程池采用半同步/半反应堆模式,有效平衡了性能和资源利用率:

template<typename T>
class ThreadPool {
public:
    ThreadPool(int thread_number = 8, int max_requests = 10000);
    ~ThreadPool();
    bool append(T* request);

private:
    static void* worker(void* arg);
    void run();

    int m_thread_number;        // 线程池中的线程数
    int m_max_requests;         // 请求队列中允许的最大请求数
    pthread_t* m_threads;       // 描述线程池的数组
    std::list<T*> m_workqueue;  // 请求队列
    Locker m_queuelocker;       // 保护请求队列的互斥锁
    Sem m_queuestat;            // 是否有任务需要处理
    bool m_stop;                // 是否结束线程
};
3. HTTP连接请求处理

HTTP连接处理采用状态机模式,支持GET和POST请求的解析:

mermaid

4. 数据库连接池实现

数据库连接池使用单例模式,通过信号量控制连接数量:

class ConnectionPool {
public:
    static ConnectionPool* GetInstance();
    MYSQL* GetConnection();                 // 获取数据库连接
    bool ReleaseConnection(MYSQL* conn);    // 释放连接
    int GetFreeConn();                      // 获取空闲连接数量
    void DestroyPool();                     // 销毁所有连接

private:
    ConnectionPool();
    ~ConnectionPool();
    MYSQL* CreateConnection();              // 创建一个连接
    void InitConnectionPool(int initialSize);// 初始化连接池

    std::string m_url;              // 数据库地址
    std::string m_Port;             // 数据库端口
    std::string m_User;             // 用户名
    std::string m_PassWord;         // 密码
    std::string m_DatabaseName;     // 数据库名
    int m_MaxSize;                  // 最大连接数
    int m_CurSize;                  // 当前已建立的连接数
    int m_FreeSize;                 // 当前空闲的连接数
    std::list<MYSQL*> m_ConnList;   // 连接池
    Locker m_lock;
    Sem m_reserve;
};

性能优化策略

1. epoll事件处理优化

TinyWebServer支持ET(边缘触发)和LT(水平触发)两种模式,开发者可以根据具体场景选择:

触发模式优点缺点适用场景
ET模式减少epoll_wait调用次数,更高性能需要一次性处理所有数据高并发场景
LT模式编程简单,不容易遗漏事件性能相对较低开发调试阶段
2. 日志系统设计

日志系统支持同步和异步两种写入方式:

class Log {
public:
    static Log* get_instance() {
        static Log instance;
        return &instance;
    }
    
    bool init(const char* file_name, int log_buf_size = 8192, 
              int split_lines = 5000000, int max_queue_size = 0);
    
    void write_log(int level, const char* format, ...);
    void flush(void);

private:
    Log();
    virtual ~Log();
    void* async_write_log() {
        std::string single_log;
        while (m_log_queue->pop(single_log)) {
            m_mutex.lock();
            fputs(single_log.c_str(), m_fp);
            m_mutex.unlock();
        }
    }

    char dir_name[128];    // 路径名
    char log_name[128];    // log文件名
    int m_split_lines;     // 日志最大行数
    int m_log_buf_size;    // 日志缓冲区大小
    long long m_count;     // 日志行数记录
    int m_today;           // 记录当前时间是哪一天
    FILE* m_fp;            // 打开log的文件指针
    char* m_buf;
    BlockQueue<std::string>* m_log_queue; // 阻塞队列
    bool m_is_async;       // 是否同步标志位
    Locker m_mutex;
};

实战开发指南

1. 环境搭建与配置

系统要求:

  • Ubuntu 16.04或更高版本
  • MySQL 5.7.29或更高版本
  • GCC编译器支持C++11标准

数据库配置:

CREATE DATABASE yourdb;
USE yourdb;

CREATE TABLE user (
    username CHAR(50) NULL,
    passwd CHAR(50) NULL
) ENGINE=InnoDB;

INSERT INTO user (username, passwd) VALUES('testuser', 'testpass');
2. 编译与运行
# 克隆项目
git clone https://gitcode.com/gh_mirrors/in/introduce_c-cpp_manual

# 编译项目
cd TinyWebServer
./build.sh

# 启动服务器
./server

# 个性化启动参数示例
./server -p 9007 -l 1 -m 0 -o 1 -s 10 -t 10 -c 1 -a 1
3. 压力测试

使用Webbench进行压力测试,典型配置下可达到:

模式组合QPS性能
Proactor, LT + LT93,251
Proactor, LT + ET97,459
Proactor, ET + LT80,498
Proactor, ET + ET92,167
Reactor, LT + ET69,175

常见问题与解决方案

1. 内存泄漏检测

使用Valgrind工具进行内存泄漏检测:

valgrind --leak-check=full --show-leak-kinds=all ./server
2. 性能瓶颈分析

使用perf工具进行性能分析:

perf record -g ./server
perf report
3. 连接数优化

通过调整系统参数优化最大连接数:

# 查看当前限制
ulimit -n

# 临时修改
ulimit -n 65535

# 永久修改

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值