C++ -- 动态内存分配和释放(new/delete)

在 C++ 中,newdelete 是用于‌动态内存管理 ‌的核心运算符。它们允许程序在运行时从‌**堆区(Heap/Free Store)**‌申请和释放内存,这与编译时确定大小的栈区内存不同。

以下是 newdelete 的详细用法、核心特性及注意事项。

1. 基本语法与步骤

使用堆区内存通常遵循以下四个步骤:

  1. 声明指针‌:定义一个指向特定类型的指针变量。
  2. 申请内存 ‌:使用 new 运算符向系统申请内存,并将返回的地址赋值给指针。
  3. 使用内存 ‌:通过解引用指针(*ptr)或箭头运算符(ptr->member)访问和操作内存中的数据。
  4. 释放内存 ‌:当不再需要该内存时,使用 delete 运算符释放它,防止内存泄漏。
1.1 单个变量的分配与释放
cpp 复制代码
#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[] 来释放,否则会导致未定义行为(通常表现为内存泄漏或程序崩溃)。

cpp 复制代码
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,主要区别如下:

cpp 复制代码
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 形式:

cpp 复制代码
#include <new> // 需要包含此头文件

int* p = new (std::nothrow) int;
if (p == nullptr) {
    cout << "内存分配失败" << endl;
} else {
    // 使用内存
    delete[] p;
}
3.2 常见错误与最佳实践
  1. 匹配使用‌:

    • new 对应 delete
    • new[] 对应 delete[]
    • 严禁混用 ‌:用 delete 释放 new[] 分配的数组,或用 free 释放 new 分配的内存,都会导致未定义行为。
  2. 避免内存泄漏‌:

    • 确保每一个 new 都有对应的 delete
    • 如果在 new 之后、delete 之前发生了异常或提前返回,内存可能无法释放。建议使用智能指针(如 std::unique_ptrstd::shared_ptr)来自动管理生命周期,这是现代 C++ 的首选方式。
  3. 避免野指针‌:

    • 执行 delete p 后,指针 p 仍然指向原来的地址(即悬空指针)。再次使用 *pdelete p 会导致严重错误。
    • 习惯 ‌:删除后立即将指针赋值为 nullptr (p = nullptr;)。
  4. 不要重复释放‌:

    • 对同一个指针执行两次 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,以从根本上杜绝内存泄漏和悬空指针问题。
相关推荐
Chester_19991 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
EXI-小洲2 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
会周易的程序员3 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
机器视觉知识推荐、就业指导3 小时前
为什么老说“纯 Qt 没啥就业市场”?
开发语言·qt
telepan3 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?
开发语言·qt
小灰灰搞电子3 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
QT界面美化性能优化3 小时前
QT+AI:使用AI技术为QT应用程序赋能
c++·人工智能·qt·opencv·qt教程·qt6.3
m0_695251493 小时前
Qt MaintenanceTool 使用国内镜像加速下载(超详细教程)
开发语言·qt
大衛說4 小时前
《Python 从入门到精通》系列总览与学习路线
开发语言·python·学习
学习星球5 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode