三、new 和 delete, new [], delete []
概念: 当我们声明一个变量时,系统会自动在合适的地方为它分配内存。需要在程序运行的过程中动态地申请内存,用 new 运算符;不需要这块内存时,使用 delete 运算符归还系统,防止“内存垃圾”。
new: 用于在堆区 (Heap) 动态地分配一块指定类型的内存空间,并返回指向该内存空间的指针。delete: 用于释放由new分配的单个对象的内存。new []: 用于在堆区动态地分配一块数组的内存空间,并返回指向数组首元素的指针。delete []: 用于释放由new []分配的数组的内存。必须使用delete []来释放数组内存,以确保所有数组元素的析构函数都被调用(如果元素是对象的话)。
示例代码:
#include <iostream>
int main() {
// 使用 new 分配一个 int 类型的内存空间
int* ptr = new int;
*ptr = 10;
std::cout << "ptr 指向的值: " << *ptr << std::endl;
// 使用 delete 释放内存
delete ptr;
ptr = nullptr; // 释放后将指针置空,防止悬 dangling 指针
std::cout << std::endl;
// 使用 new [] 分配一个包含 5 个 int 类型的数组
int* arr = new int[5];
for (int i = 0; i < 5; ++i) {
arr[i] = i * 2;
}
std::cout << "动态分配的数组元素:";
for (int i = 0; i < 5; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
// 使用 delete [] 释放数组内存
delete[] arr;
arr = nullptr; // 释放后将指针置空
return 0;
}
讲解要点:
- 动态内存分配的必要性:
- 灵活地管理内存: 在程序运行时根据需要动态地申请和释放内存,避免了静态分配内存可能造成的浪费或不足。
- 创建动态数据结构: 例如链表、树等,这些数据结构的...在编译时无法确定大小,需要动态分配内存。
new和delete的使用方法:类型* 指针变量 = new 类型;分配单个对象的内存。类型* 指针变量 = new 类型[大小];分配数组的内存。delete 指针变量;释放单个对象的内存。delete[] 指针变量;释放数组的内存。
- 内存泄漏的概念和危害: 如果使用
new分配了内存,但在不再使用时忘记使用delete或delete[]释放,就会导致内存泄漏 (Memory Leak)。 随着程序的运行,泄漏的内存会越来越多,最终可能导致程序运行缓慢甚至崩溃。 想象一下你借了别人的土地却一直不归还,最终可能会引发问题。 new失败的情况: 当系统没有足够的内存来满足new的请求时,会抛出一个std::bad_alloc异常。 良好的编程习惯是使用try-catch块来捕获这个异常并进行处理。- 悬 dangling 指针: 当
delete或delete[]释放了指针所指向的内存后,该指针就变成了悬 dangling 指针,它指向的内存已经无效。 访问悬 dangling 指针会导致未定义的行为,程序可能会崩溃或产生不可预测的结果。 因此,在释放内存后,通常会将指针设置为nullptr。