C++智能指针、单例模式、线程池、String
·

智能指针
智能指针概述:RAII机制与内存管理
智能指针是C++中基于RAII(Resource Acquisition Is Initialization)机制的高级内存管理工具,通过对象生命周期的自动化管理来确保资源的正确获取和释放。其核心原理是将资源获取与对象构造绑定,资源释放与对象析构绑定,从而避免内存泄漏和资源未释放等问题。
在实际应用中,智能指针主要有以下几种类型:
- unique_ptr:独占所有权的智能指针,不允许拷贝,只允许移动
- shared_ptr:共享所有权的智能指针,使用引用计数机制
- weak_ptr:不控制对象生命周期的智能指针,通常与shared_ptr配合使用
智能指针的工作流程示例:
- 构造阶段:当智能指针对象被创建时,自动获取资源
- 使用阶段:通过重载的operator->和operator*提供对原始指针的访问
- 析构阶段:当智能指针对象离开作用域时,自动调用析构函数释放资源
典型应用场景包括:
- 动态分配对象的生命周期管理
- 异常安全保证(即使在抛出异常时也能正确释放资源)
- 作为函数返回值或参数传递时确保资源所有权清晰
相比原始指针,智能指针的优势在于:
- 自动内存管理,减少内存泄漏风险
- 明确所有权语义,提高代码可读性
- 支持自定义删除器,可以管理非内存资源(如文件句柄、网络连接等)
在现代C++开发中,智能指针已经成为管理动态内存的首选方式,是编写异常安全、资源安全代码的重要工具。
// RAII示例
class FileHandle {
public:
FileHandle(const char* filename) : handle(fopen(filename, "r")) {}
~FileHandle() { if(handle) fclose(handle); }
private:
FILE* handle;
};
常见智能指针类型
| 类型 | 所有权 | 线程安全 | 典型用途 |
|---|---|---|---|
| unique_ptr | 独占 | 否 | 资源唯一所有者 |
| shared_ptr | 共享 | 是(引用计数) | 共享资源 |
| weak_ptr | 无 | 是 | 打破循环引用 |
// unique_ptr示例
std::unique_ptr<Widget> p1 = std::make_unique<Widget>();
// shared_ptr示例
std::shared_ptr<Widget> p2 = std::make_shared<Widget>();
使用场景分析
- 所有权转移:unique_ptr通过移动语义转移所有权
std::unique_ptr<Widget> p3 = std::move(p1);
- 循环引用问题:shared_ptr相互引用导致内存泄漏
struct Node {
std::shared_ptr<Node> next; // 改为weak_ptr解决循环引用
};
性能对比与注意事项
- make_shared比直接构造shared_ptr效率更高(单次内存分配)
- 避免从原始指针创建多个shared_ptr
- weak_ptr不增加引用计数,需先lock()获取shared_ptr
单例模式
设计模式基础
单例确保类只有一个实例,并提供全局访问点。适用于:
- 配置管理
- 日志系统
- 资源池管理
经典实现
// 懒汉式(线程不安全)
class Singleton {
public:
static Singleton& getInstance() {
if(!instance) instance = new Singleton();
return *instance;
}
private:
static Singleton* instance;
Singleton() = default;
};
线程安全解决方案
// 双重检查锁定(C++11后)
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance; // C++11保证线程安全
return instance;
}
private:
Singleton() = default;
};
C++11改进
// Meyer's Singleton (最优实现)
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
// 其他成员...
};
线程池
核心概念
线程池组成:
- 任务队列:存储待执行任务
- 工作线程:从队列获取任务执行
class ThreadPool {
public:
ThreadPool(size_t threads) {
for(size_t i = 0; i < threads; ++i)
workers.emplace_back([this] {
while(!stop) {
Task task;
if(queue.try_pop(task)) task();
}
});
}
// 其他实现...
};
关键组件
- 任务抽象:使用std::function封装可调用对象
- 线程管理:std::thread与条件变量配合
性能优化技术
- 无锁队列:boost::lockfree::queue
- 动态扩容:根据负载增减线程
- 工作窃取:平衡线程负载
String深度解析
内存优化技术
| 优化技术 | 原理 | 适用场景 | 缺点 |
|---|---|---|---|
| SSO | 小字符串直接存储 | <15字符 | 无 |
| COW | 共享内存副本 | 读多写少 | 线程不安全 |
// SSO示例
std::string s1 = "short"; // 栈分配
std::string s2 = "very long string..."; // 堆分配
编码处理
- UTF-8:跨平台兼容但需特殊处理多字节字符
std::u8string utf8_str = u8"中文";
高效操作
- 移动语义避免拷贝
std::string getString() {
std::string s(1000, 'x');
return s; // 触发移动语义
}
- reserve预分配内存
std::string s;
s.reserve(1000); // 避免多次扩容
string_view应用
void process(std::string_view sv) {
// 不拥有数据,零成本抽象
}
综合应用案例
线程池与智能指针结合
class Task {
public:
virtual ~Task() = default;
virtual void execute() = 0;
};
using TaskPtr = std::unique_ptr<Task>;
class ThreadPool {
// 使用unique_ptr管理任务生命周期
std::queue<TaskPtr> tasks;
};
性能测试指标
- 任务吞吐量
- 内存使用情况
- 线程切换开销
调试技巧
- 使用Valgrind检测内存泄漏
- 线程死锁检测
- 性能剖析工具(gperftools)
classDiagram
class ThreadPool {
+addTask(TaskPtr)
+stop()
-workers: vector<thread>
-tasks: queue<TaskPtr>
}
class Task {
<<interface>>
+execute()
}
ThreadPool o-- Task : contains
注意:所有代码示例需要C++17及以上编译器支持,建议使用GCC 9+/Clang 10+/MSVC 19.28+版本。
更多推荐

所有评论(0)