1. 栈内存 (Stack Memory)
栈内存是自动管理的,即当变量在函数作用域内声明时,它们会自动分配在栈上,当作用域结束时,内存会自动释放。栈内存的分配和释放非常高效,但其生命周期受限于作用域。
void stackMemoryExample() {
int a = 10; // a 在栈上分配
// a 会在函数结束时自动释放
}
2. 堆内存 (Heap Memory)
堆内存由程序员手动管理,使用 new 进行分配,使用 delete 进行释放。堆内存的生命周期不受限于作用域,可以在不同函数之间共享。
动态分配单个变量
void heapMemoryExample() {
int* p = new int; // 分配一个 int 型变量
*p = 20; // 使用该变量
delete p; // 释放内存
}
动态分配数组
void heapMemoryArrayExample() {
int* arr = new int[10]; // 分配一个 int 型数组
for (int i = 0; i < 10; ++i) {
arr[i] = i * i;
}
delete[] arr; // 释放数组内存
}
3. 内存泄漏 (Memory Leak)
如果在使用 new 分配内存后没有使用 delete 释放内存,就会导致内存泄漏。内存泄漏会导致程序占用的内存越来越多,最终可能导致系统资源耗尽。
4. 智能指针 (Smart Pointers)
为了避免内存泄漏,C++11 引入了智能指针,它们可以自动管理堆内存。常见的智能指针有 std::unique_ptr 和 std::shared_ptr。
std::unique_ptr
std::unique_ptr 表示独占所有权的指针,内存会在指针销毁时自动释放。
#include <memory>
void uniquePtrExample() {
std::unique_ptr<int> p = std::make_unique<int>(10); // 自动释放内存
}
std::shared_ptr
std::shared_ptr 表示共享所有权的指针,引用计数为零时自动释放内存。
#include <memory>
void sharedPtrExample() {
std::shared_ptr<int> p1 = std::make_shared<int>(20);
{
std::shared_ptr<int> p2 = p1; // 引用计数增加
} // p2 作用域结束,引用计数减少
// p1 作用域结束,引用计数为零,释放内存
}
5. 内存对齐 (Memory Alignment)
内存对齐是指数据在内存中的存储地址需要满足特定的对齐要求,以提高访问效率和性能。C++ 提供了 alignas 和 alignof 关键字来处理内存对齐。
struct MyStruct
{
char c;
int i;
short s;
};
大小为12字节
c—iiii
ss–
后跟2字节填充以确保结构体的整体大小是对齐单位的倍数。
占12字节
对齐办法
#pragma pack(push, 1) // 设定1字节对齐
struct PackedStruct {
char c;
int i;
short s;
};
#pragma pack(pop) // 恢复默认对齐
struct alignas(16) AlignedStruct {
int x;
double y;
};
void alignmentExample() {
AlignedStruct a;
std::cout << "Alignment of AlignedStruct: " << alignof(AlignedStruct) << std::endl;
}
6. 自定义内存管理器
在某些情况下,可以编写自定义的内存管理器,以提高内存分配和释放的效率,特别是在需要大量小对象频繁分配和释放时。
class MemoryPool {
public:
MemoryPool(size_t size) : poolSize(size), pool(new char[size]), freeList(nullptr) {}
~MemoryPool() { delete[] pool; }
void* allocate(size_t size) {
if (freeList) {
void* result = freeList;
freeList = *(void**)freeList;
return result;
}
if (poolSize < size) return nullptr;
void* result = pool;
pool += size;
poolSize -= size;
return result;
}
void deallocate(void* ptr) {
*(void**)ptr = freeList;
freeList = ptr;
}
private:
size_t poolSize;
char* pool;
void* freeList;
};
void customMemoryManagerExample() {
MemoryPool pool(1024);
int* p1 = (int*)pool.allocate(sizeof(int));
pool.deallocate(p1);
}