1. C++课后习题训练记录Day78
今天是我坚持C++课后习题训练的第78天。作为一名计算机专业的学生,我深知编程能力的提升离不开持续的练习和积累。通过这78天的坚持,我不仅巩固了C++的基础知识,还培养了解题思维和代码实现能力。
1.1 今日练习内容
今天的练习主要围绕以下几个知识点展开:
- 动态内存管理
- 智能指针的使用
- 异常处理机制
- 模板编程基础
我选择了一道综合性较强的题目,要求实现一个简单的内存池管理系统。这个系统需要能够动态分配和释放内存,同时要处理可能出现的异常情况。
1.2 解题思路分析
首先,我需要设计一个MemoryPool类,它应该包含以下功能:
- 预分配一大块内存作为内存池
- 提供allocate和deallocate方法
- 使用智能指针管理内存资源
- 实现异常安全
考虑到内存管理的复杂性,我决定使用std::unique_ptr来管理内存资源,这样可以避免内存泄漏的问题。同时,我会使用模板技术使内存池能够适用于不同类型的数据。
1.3 代码实现细节
cpp复制#include <memory>
#include <vector>
#include <stdexcept>
template <typename T>
class MemoryPool {
public:
explicit MemoryPool(size_t size) : poolSize(size) {
try {
// 预分配内存
pool = std::make_unique<T[]>(poolSize);
freeList.resize(poolSize, true);
} catch (const std::bad_alloc& e) {
throw std::runtime_error("Failed to allocate memory pool");
}
}
T* allocate() {
for (size_t i = 0; i < poolSize; ++i) {
if (freeList[i]) {
freeList[i] = false;
return &pool[i];
}
}
throw std::runtime_error("Memory pool exhausted");
}
void deallocate(T* ptr) {
if (ptr < &pool[0] || ptr > &pool[poolSize - 1]) {
throw std::runtime_error("Invalid pointer - not from this pool");
}
size_t index = ptr - &pool[0];
freeList[index] = true;
}
private:
std::unique_ptr<T[]> pool;
std::vector<bool> freeList;
size_t poolSize;
};
1.4 测试用例编写
为了验证内存池的正确性,我编写了以下测试用例:
cpp复制#include <iostream>
#include <cassert>
void testMemoryPool() {
try {
// 测试基本分配和释放
MemoryPool<int> pool(10);
int* p1 = pool.allocate();
*p1 = 42;
assert(*p1 == 42);
pool.deallocate(p1);
// 测试异常情况
bool exceptionThrown = false;
try {
MemoryPool<int> largePool(10000000000); // 尝试分配过大内存
} catch (const std::runtime_error& e) {
exceptionThrown = true;
}
assert(exceptionThrown);
std::cout << "All tests passed!" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Test failed: " << e.what() << std::endl;
}
}
int main() {
testMemoryPool();
return 0;
}
1.5 遇到的问题及解决方案
在实现过程中,我遇到了几个问题:
-
内存对齐问题:最初的设计没有考虑内存对齐,可能导致性能问题。解决方案是使用alignas关键字或标准库提供的对齐分配函数。
-
异常安全问题:在构造函数中,如果freeList的分配失败,已经分配的pool内存可能会泄漏。通过使用std::make_unique和try-catch块解决了这个问题。
-
指针验证:在deallocate方法中,需要验证传入的指针确实属于这个内存池。通过比较指针地址范围实现了这一功能。
1.6 性能优化思考
虽然当前实现已经满足基本功能,但还有优化空间:
- 可以使用位图代替bool向量来记录空闲块,节省空间。
- 实现更高效的空闲块查找算法,如首次适应、最佳适应等。
- 考虑添加线程安全机制,使内存池可以在多线程环境中使用。
1.7 学习收获总结
通过今天的练习,我获得了以下收获:
- 深入理解了动态内存管理的原理和实现方式。
- 掌握了智能指针在资源管理中的应用。
- 强化了异常安全编程的意识。
- 实践了模板编程技术。
- 学会了如何设计简单的内存池系统。
坚持每日练习确实让我感受到了编程能力的提升。虽然有时会遇到困难,但通过查阅资料、思考和实践,最终都能找到解决方案。这种持续学习的过程让我对C++的理解越来越深入。