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的各个组件进行精心拆分和实现。整个项目结构清晰,代码风格统一,注释详细,特别适合初学者学习和参考。
核心容器实现详解
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实现了完整的迭代器体系,包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器。
算法库的实现技巧
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在性能优化方面做了大量工作,主要包括:
- 内联函数优化:对小型函数进行内联处理
- 移动语义支持:充分利用C++11的移动语义
- 内存池技术:减少内存分配开销
- 算法选择:根据数据特征选择最优算法
// 移动构造函数示例
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的实现,我们可以总结出以下最佳实践:
- 模块化设计:将功能分解为独立的模块
- 接口一致性:保持与标准STL相同的接口
- 异常安全:确保资源管理的安全性
- 性能优化:在保证正确性的前提下进行优化
- 完整测试:建立全面的测试体系
学习价值与应用场景
MyTinySTL不仅是一个学习项目,其设计思想和实现技巧在实际开发中也有广泛应用:
- 嵌入式开发:轻量级的STL实现适合资源受限环境
- 教学示范:优秀的代码规范和注释适合教学使用
- 性能敏感场景:自定义内存分配器可优化特定场景性能
- 跨平台开发:不依赖特定平台的标准库实现
通过深入研究和实践MyTinySTL,开发者能够全面提升对C++语言特性、模板编程、内存管理、算法设计等核心技术的理解,为成为高级C++工程师奠定坚实基础。
TinyWebServer:轻量级网络服务器开发
在当今互联网时代,网络服务器是支撑各种Web应用的核心基础设施。TinyWebServer作为一个用C++实现的轻量级Web服务器项目,不仅展示了高性能服务器编程的精髓,更为初学者提供了一个绝佳的学习平台。本文将深入探讨TinyWebServer的核心架构、关键技术实现以及开发实践。
项目概述与技术架构
TinyWebServer采用了现代化的服务器设计模式,集成了多种高性能编程技术,构建了一个完整的B/S模型Web服务器。其核心架构基于以下技术组合:
核心技术栈:
- 线程池 + 非阻塞socket:实现高效的并发处理
- epoll(ET和LT模式):提供高性能的I/O多路复用
- 事件处理模型:支持Reactor和模拟Proactor两种模式
- 状态机解析:用于HTTP请求报文解析
- 数据库连接池:优化数据库访问性能
- 同步/异步日志系统:记录服务器运行状态
核心模块详解
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请求的解析:
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 + LT | 93,251 |
| Proactor, LT + ET | 97,459 |
| Proactor, ET + LT | 80,498 |
| Proactor, ET + ET | 92,167 |
| Reactor, LT + ET | 69,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),仅供参考



