)
在 C 中new和delete是用于动态内存管理的核心运算符。它们允许程序在运行时从堆区Heap/Free Store申请和释放内存这与编译时确定大小的栈区内存不同。以下是new和delete的详细用法、核心特性及注意事项。1. 基本语法与步骤使用堆区内存通常遵循以下四个步骤声明指针定义一个指向特定类型的指针变量。申请内存使用new运算符向系统申请内存并将返回的地址赋值给指针。使用内存通过解引用指针*ptr或箭头运算符ptr-member访问和操作内存中的数据。释放内存当不再需要该内存时使用delete运算符释放它防止内存泄漏。1.1 单个变量的分配与释放#include iostream using namespace std; int main() { // 1. 声明指针 int* p nullptr; // 2. 申请内存 (new) // 语法: new 数据类型(初始值); p new int(10); // 申请一个 int 大小的内存并初始化为 10 // 3. 使用内存 cout *p endl; // 输出: 10 *p 20; // 修改值 cout *p endl; // 输出: 20 // 4. 释放内存 (delete) // 语法: delete 指针变量; delete p; p nullptr; // 建议释放后将指针置空避免成为野指针 return 0; }1.2 数组的分配与释放如果需要使用new分配数组必须使用delete[]来释放否则会导致未定义行为通常表现为内存泄漏或程序崩溃。int main() { // 1. 申请数组内存 // 语法: new 数据类型[元素个数]; int* arr new int; // 2. 使用数组 for(int i 0; i 5; i) { arr[i] i * 10; } // 3. 释放数组内存 // 注意必须使用 delete[]而不是 delete delete[] arr; arr nullptr; return 0; }2. new/delete 与 malloc/free 的区别虽然 C 语言的malloc/free也能进行动态内存管理但 C 推荐使用new/delete主要区别如下class Student { public: Student(int age) : m_age(age) { cout 构造函数被调用 endl; } ~Student() { cout 析构函数被调用 endl; } private: int m_age; }; int main() { // 使用 new自动调用构造函数 Student* s new Student(18); // 使用 delete自动调用析构函数 delete s; return 0; } // 输出: // 构造函数被调用 // 析构函数被调用3. 高级用法与注意事项3.1 内存分配失败的处理标准的new在失败时会抛出异常。如果你希望它在失败时返回nullptr而不是抛出异常可以使用nothrow形式#include new // 需要包含此头文件 int* p new (std::nothrow) int; if (p nullptr) { cout 内存分配失败 endl; } else { // 使用内存 delete[] p; }3.2 常见错误与最佳实践匹配使用new对应deletenew[]对应delete[]严禁混用用delete释放new[]分配的数组或用free释放new分配的内存都会导致未定义行为。避免内存泄漏确保每一个new都有对应的delete。如果在new之后、delete之前发生了异常或提前返回内存可能无法释放。建议使用智能指针如std::unique_ptr或std::shared_ptr来自动管理生命周期这是现代 C 的首选方式。避免野指针执行delete p后指针p仍然指向原来的地址即悬空指针。再次使用*p或delete p会导致严重错误。习惯删除后立即将指针赋值为nullptr(p nullptr;)。不要重复释放对同一个指针执行两次delete是未定义行为。如果指针已置为nullptr再次delete nullptr是安全的无操作。4. 总结简单类型new int(10)-delete p数组类型new int-delete[] p类对象new Class()-delete p(自动调用构造/析构)现代 C 建议尽量使用智能指针std::unique_ptr,std::shared_ptr替代裸指针的手动new/delete以从根本上杜绝内存泄漏和悬空指针问题。