Menu
CoddyTech

动态内存(new/delete)

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 14 课,共 104 课。

现在你已经了解了指针和引用,接下来让我们用它们来进行动态内存分配。new 和 delete 运算符可以让你在运行时于堆上创建和销毁对象。

使用 new 分配内存,并获取指向该内存的指针:

int* num = new int;        // 为单个整数分配内存
*num = 42;                 // 通过指针赋值

Player* player = new Player("Hero");  // 为对象分配内存

每个 new 都必须有一个匹配的 delete 来释放内存:

delete num;      // 释放单个对象
delete player;   // 调用析构函数,然后释放内存

对于数组,使用 new[] 和 delete[]:

int* scores = new int[5];    // 分配一个包含 5 个整数的数组
scores[0] = 100;

delete[] scores;             // 释放数组,注意方括号!

需要避免的常见错误:

// 内存泄漏:忘了用 delete 释放内存
int* ptr = new int(10);
ptr = new int(20);    // 无法再访问第一次分配的内存!

// 悬空指针:用 delete 释放后仍继续使用
delete ptr;
*ptr = 5;             // 未定义行为!

// delete 使用不匹配
int* arr = new int[10];
delete arr;           // 错了!应该用 delete[]

删除后,将指针设为 nullptr,以避免意外重用。手动管理内存容易出错,因此现代 C++ 更倾向于使用智能指针,我们接下来会学习它们。

challenge icon

挑战

简单

让我们构建一个简单的消息存储系统,用 new 和 delete 演示动态内存分配。

你将创建两个文件来组织代码:

  • MessageBox.h:定义一个 MessageBox 类,用于动态管理消息数组。这个类应包含:
    • 一个指向动态分配的字符串数组的私有指针
    • 一个用于记录当前消息数量的私有整数
    • 一个用于存储最大容量的私有整数
    • 一个接收容量并使用 new[] 分配数组的构造函数
    • 一个使用 delete[] 正确释放内存并打印 "MessageBox destroyed" 的析构函数
    • 一个 addMessage(string msg) 方法,有剩余空间时添加消息,成功时返回 true,已满时返回 false
    • 一个 printAll() 方法,将存储的每条消息分别打印在一行
  • main.cpp:从输入中读取容量值和消息数量,然后读取相应数量的消息字符串。使用 new 在堆上创建一个 MessageBox,将所有消息添加到其中,调用 printAll(),然后正确删除 MessageBox 以释放内存。

输入格式如下:

  • 第一行:容量(整数)
  • 第二行:要添加的消息数量(整数)
  • 后续各行:每行一条消息

请记住:每个 new 都需要匹配一个 delete,每个 new[] 都需要匹配一个 delete[]。删除后,最好将指针设为 nullptr。

在 main.cpp 中使用 #include "MessageBox.h" 引入头文件。

亲手试试

#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;

int main() {
    int capacity;
    int numMessages;
    
    // 读取容量和消息数量
    cin >> capacity;
    cin >> numMessages;
    cin.ignore(); // 清除数字后面的换行符
    
    // TODO: 使用 new 在堆上创建 MessageBox
    
    // TODO: 读取所有消息并添加到 MessageBox
    for (int i = 0; i < numMessages; i++) {
        string message;
        getline(cin, message);
        // 将消息添加到 MessageBox
    }
    
    // TODO: 调用 printAll() 显示所有消息
    
    // TODO: 删除 MessageBox 以释放内存
    // 删除后记得将指针设为 nullptr
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器