C/C++动态内存管理
C语言中的动态内存管理方式
C语言提供了以下几种动态内存管理函数:
1. malloc:分配指定大小的内存块,不初始化内容
void* malloc(size_t size);
2. calloc:分配指定数量和大小的内存块,并初始化为0
void* calloc(size_t num, size_t size);
3. realloc:调整已分配内存块的大小
void* realloc(void* ptr, size_t new_size);
4. free:释放之前分配的内存
void free(void* ptr);
示例:
int* arr = (int*)malloc(10 * sizeof(int));
if (arr == NULL)
{
// 处理分配失败
}
free(arr);
C++中的动态内存管理
C++提供了更高级的动态内存管理方式:
1. new:分配内存并调用构造函数
Type* ptr = new Type;
Type* arr = new Type[10];
2. delete:调用析构函数并释放内存
delete ptr;
delete[] arr;
operator new与operator delete函数
这些是C++中的底层内存分配/释放函数:
1. operator new:只分配内存,不调用构造函数
void* operator new(size_t size);
2. operator delete:只释放内存,不调用析构函数
void operator delete(void* ptr) noexcept;
它们可以被重载以实现自定义的内存管理策略。
new和delete的实现原理
new的实现原理
1. 调用operator new分配内存
2. 在分配的内存上调用构造函数
delete的实现原理
1. 调用对象的析构函数
2. 调用operator delete释放内存
new[]和delete[]的特殊处理
对于数组,new[]会额外存储元素数量信息,delete[]会根据这个信息调用正确次数的析构函数。
定位new表达式(placement-new)
定位new允许在已分配的内存上构造对象:
void* mem = malloc(sizeof(MyClass));
MyClass* obj = new (mem) MyClass(); // 定位new
使用场景:
1. 内存池实现
2. 需要在特定地址构造对象
3. 避免额外的内存分配开销
需要手动调用析构函数:
obj->~MyClass();
free(mem);
对比总结
C 语言和 C++ 语言在动态内存管理方面存在诸多差异,具体如下:
1. 内存分配:C 方式使用 malloc 或 calloc 函数来分配内存;而 C++ 方式则通过 new 运算符或者 operator new 函数来进行内存分配。
2. 内存释放:在 C 语言中,使用 free 函数来释放之前分配的内存;C++ 语言里,内存释放依靠 delete 运算符或者 operator delete 函数来完成。
3. 构造/析构:C 语言在动态内存管理中没有自动调用构造函数和析构函数的机制;C++ 语言在使用 new 分配内存时会自动调用构造函数,使用 delete 释放内存时会自动调用析构函数。
4. 类型安全:C 语言使用 malloc 等函数分配内存时需要进行类型转换,否则可能会出现类型不匹配等问题;C++ 语言的 new 运算符具有类型安全的特性,不需要额外进行类型转换。
5. 异常处理:C 语言中的 malloc 等函数在内存分配失败时通常返回 NULL ,需要程序员手动检查并处理;C++ 语言中的 new 运算符在内存分配失败时会抛出 bad_alloc 异常,通过异常处理机制来处理错误情况。
6. 自定义分配策略:在 C 语言中实现自定义的内存分配策略比较困难;C++ 语言则可以通过重载 operator new 和 operator delete 函数来实现自定义的内存管理策略,更加灵活方便。
总体而言,C++ 的方式更安全、更方便,特别是在处理类对象时,因为它能自动管理构造和析构。