动态内存(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++ 更倾向于使用智能指针,我们接下来会学习它们。
挑战
简单让我们构建一个简单的消息存储系统,用 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;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器