16、动态内存管理
大约 3 分钟C++C++基础编程程序厨
内存管理
内存管理有几个相关概念我们需要掌握:
- 堆****内存:由程序员手动分配和释放的内存区域,生命周期由程序员控制。
- 栈****内存:由编译器自动分配和释放的内存区域,生命周期与作用域绑定。
- 内存****泄漏:程序未释放不再使用的堆内存,导致内存占用不断增加。
- 悬空指针:指针指向的内存已被释放,但指针仍又被使用。
内存管理的原则:
- 谁分配,谁释放:确保每个动态分配的内存都有对应的释放操作。
- 避免重复释放:同一块内存只能释放一次。
- 避免悬空指针:释放内存后,将指针置为
nullptr
。
示例代码:
#include <iostream>
int main() {
int* ptr = new int(42); // 分配堆内存
std::cout << "Value: " << *ptr << std::endl; // 输出:42
delete ptr; // 释放堆内存
ptr = nullptr; // 避免悬空指针
if (ptr) {
std::cout << "Pointer is not null." << std::endl;
} else {
std::cout << "Pointer is null." << std::endl; // 输出:Pointer is null.
}
return 0;
}
C++
中的动态内存管理是指在程序运行时,根据需要从堆(heap)中分配和释放内存。与栈内存不同,堆内存的生命周期由程序员手动控制,因此需要更加谨慎地管理。
new
和delete
的基本用法
- **
new
**运算符:用于在堆上分配内存,并返回指向该内存的指针。 - **
delete
**运算符:用于释放由new
分配的内存。
代码示例:
#include <iostream>
using namespace std;
int main() {
// 动态分配一个 int 类型的内存
int* p = new int;
*p = 10;
cout << *p << endl;
// 释放内存
delete p;
return 0;
}
new[]
和delete[]
new[]
运算符:用于在堆上分配数组内存。delete[]
运算符:用于释放由new[]
分配的数组内存。
代码示例:
#include <iostream>
using namespace std;
int main() {
// 动态分配一个包含 5 个 int 元素的数组
int* arr = new int[5];
for (int i = 0; i < 5; ++i) {
arr[i] = i + 1;
}
// 释放数组内存
delete[] arr;
return 0;
}
new[]
和delete[]
一定要配对使用。
new
和delete
,new[]
和delete[]
为什么要配对使用 - 内存泄漏: 如果只分配内存而不释放,会导致内存泄漏,最终耗尽系统内存。
- 未定义行为: 使用
delete
释放new[]
分配的内存,或者使用delete[]
释放new
分配的内存,都会导致未定义行为。
placement new
placement new
是个进阶知识点了,它允许程序员在已分配的内存上构造对象,而不会分配新的内存,只是使用指定的内存地址。
代码示例:
#include <iostream>
using namespace std;
struct A {
A(int a): a_(a) {}
void print() {
std::cout << a_ << std::endl;
}
int a_;
};
int main() {
// 预先分配内存
char* buffer = new char[sizeof(int)];
// 在 buffer 上构造 A 对象
A* p = new (buffer) A(10);
p->print();
// 显式调用析构函数
p->~A();
// 释放内存
delete[] buffer;
return 0;
}
new
和 malloc
的区别
特性 | new | malloc |
---|---|---|
语言 | C++ 运算符 | C 库函数 |
返回值 | 返回具体类型指针 | 返回 void* |
失败处理 | 抛出 std::bad_alloc 异常 | 返回 NULL |
内存大小 | 自动计算 | 需要手动计算 |
构造函数 | 调用构造函数 | 不调用构造函数 |
析构函数 | 调用析构函数 | 不调用析构函数 |
重载 | 可以重载 | 不能重载 |
代码示例:
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
// 使用 new 分配内存
int* p1 = new int(10);
cout << *p1 << endl;
delete p1;
// 使用 malloc 分配内存
int* p2 = (int*)malloc(sizeof(int));
*p2 = 20;
cout << *p2 << endl;
free((void*)p2);
return 0;
}
练习题
- 编写一个程序,动态分配一个包含 10 个
double
类型元素的数组,并初始化数组元素为 1.0 到 10.0,最后释放数组内存。 - 编写一个程序,使用
placement new
在一个预先分配的char
数组上构造一个自定义class
对象,并调用自定义class
的相关函数。
