在 C++ 编程中,当我们使用 new 操作符动态分配内存时,必须使用对应的 delete 操作符来释放内存。并且, new 和 delete 的使用形式必须匹配,否则可能会导致严重的错误。
一、 new 与 delete 的基本形式
new 操作符有多种形式,例如:
cpp
int* ptr = new int; // 分配单个整数的内存
int* arr = new int[10]; // 分配整数数组的内存
对应的 delete 形式应该是:
cpp
delete ptr; // 释放单个对象的内存
delete[] arr; // 释放数组的内存
二、不匹配使用的后果
如果在释放内存时,使用了错误的形式,可能会产生以下问题:
1. 内存泄漏:如果使用 delete 来释放通过 new[] 分配的数组内存,或者使用 delete[] 来释放通过 new 分配的单个对象内存,可能导致部分内存未被正确释放,造成内存泄漏。
2. 未定义行为:这可能导致程序崩溃、数据损坏或者其他难以预测的错误。
三、正确的实践
为了避免这些问题,我们应该始终确保 new 和 delete 的使用形式严格匹配:
1. 清晰记录内存分配的方式,以便在释放时能够正确选择 delete 或 delete[] 。
2. 尽量使用智能指针(如 std::unique_ptr 和 std::shared_ptr )来管理动态分配的内存,它们可以自动处理内存的释放,减少出错的可能性。
四、复杂的使用场景
1. 当你撰写的 class 含有一个指针指向动态分配内存,并提供多个构造函数时,上述规则尤其重要,因为这种情况下你必须小心地在所有构造函数中使用相同形式的 new 将指针成员初始化。如果没这样做,又如何知道该在析构函数中使用什么形式的 delete 呢?
例如:
cpp
class MyComplexClass {
int* data;
public:
MyComplexClass() {
data = new int;
}
MyComplexClass(int size) {
data = new int[size];
}
~MyComplexClass() {
// 如果不确定构造函数中使用的是哪种 new 形式,这里的 delete 就可能出错
// 如果所有构造函数都使用 new[],这里就应该用 delete[]
// 如果有使用 new,就应该用 delete
delete data;
}
};
2. 这个规则对于喜欢使用 typedef 的人也很重要,因为它意味 typedef 的作者必须说清楚,当程序员以 new 创建该种 typedef 类型对象时,该以哪一种 delete 形式删除之。考虑下面这个 typedef :
cpp
typedef int* IntPtr;
// 如果程序员这样使用
IntPtr ptr = new int;
// 那么就应该用 delete 来释放
delete ptr;
// 而如果是
IntPtr arr = new int[10];
// 就应该用 delete[] 来释放
delete[] arr;
总之,在 C++ 中,成对使用 new 和 delete 时采取相同的形式是非常重要的,这有助于确保程序的正确性和稳定性。