C++——`new` 和 `delete`, `new []`, `delete []`

52 阅读3分钟

三、newdelete, 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;
}

讲解要点:

  • 动态内存分配的必要性:
    • 灵活地管理内存: 在程序运行时根据需要动态地申请和释放内存,避免了静态分配内存可能造成的浪费或不足。
    • 创建动态数据结构: 例如链表、树等,这些数据结构的...在编译时无法确定大小,需要动态分配内存。
  • newdelete 的使用方法:
    • 类型* 指针变量 = new 类型; 分配单个对象的内存。
    • 类型* 指针变量 = new 类型[大小]; 分配数组的内存。
    • delete 指针变量; 释放单个对象的内存。
    • delete[] 指针变量; 释放数组的内存。
  • 内存泄漏的概念和危害: 如果使用 new 分配了内存,但在不再使用时忘记使用 deletedelete[] 释放,就会导致内存泄漏 (Memory Leak)。 随着程序的运行,泄漏的内存会越来越多,最终可能导致程序运行缓慢甚至崩溃。 想象一下你借了别人的土地却一直不归还,最终可能会引发问题。
  • new 失败的情况: 当系统没有足够的内存来满足 new 的请求时,会抛出一个 std::bad_alloc 异常。 良好的编程习惯是使用 try-catch 块来捕获这个异常并进行处理。
  • 悬 dangling 指针:deletedelete[] 释放了指针所指向的内存后,该指针就变成了悬 dangling 指针,它指向的内存已经无效。 访问悬 dangling 指针会导致未定义的行为,程序可能会崩溃或产生不可预测的结果。 因此,在释放内存后,通常会将指针设置为 nullptr