在 C++ 中,new[]
和 delete[]
必须配对使用,因为它们的行为与 new
和 delete
有本质区别。混用 new[]
和 delete
或 new
和 delete[]
会导致未定义行为(undefined behavior),可能引发程序崩溃或内存泄漏。
为什么 new[]
和 delete[]
必须配对使用?
1. 内存分配和释放的机制不同
new[]
:- 用于分配数组内存。
- 除了分配内存外,还会调用每个数组元素的构造函数。
- 在分配的内存块中可能会存储数组的大小(用于
delete[]
正确释放内存)。
delete[]
:- 用于释放数组内存。
- 除了释放内存外,还会调用每个数组元素的析构函数。
- 需要知道数组的大小,以便正确调用析构函数并释放内存。
new
:- 用于分配单个对象的内存。
- 只调用单个对象的构造函数。
delete
:- 用于释放单个对象的内存。
- 只调用单个对象的析构函数。
2. 内存布局可能不同
new[]
可能会在分配的内存块中存储数组的大小,而new
不会。- 如果使用
delete
释放new[]
分配的内存,可能会导致:- 只调用第一个元素的析构函数,而其他元素的析构函数未被调用。
- 内存释放不完整,导致内存泄漏或程序崩溃。
3. 未定义行为
- 混用
new[]
和delete
或new
和delete[]
是未定义行为,具体表现取决于编译器和运行时环境,可能导致:- 程序崩溃。
- 内存泄漏。
- 数据损坏。
示例分析
1. 正确用法
class MyClass {
public:
MyClass() { std::cout << "Constructed!" << std::endl; }
~MyClass() { std::cout << "Destroyed!" << std::endl; }
};
int main() {
MyClass* arr = new MyClass[3]; // 调用 3 次构造函数
delete[] arr; // 调用 3 次析构函数
return 0;
}
输出:
Constructed!
Constructed!
Constructed!
Destroyed!
Destroyed!
Destroyed!
2. 错误用法(混用 new[]
和 delete
)
int main() {
MyClass* arr = new MyClass[3]; // 调用 3 次构造函数
delete arr; // 未定义行为:只调用第一个元素的析构函数
return 0;
}
可能的输出:
Constructed!
Constructed!
Constructed!
Destroyed!
- 只有第一个元素的析构函数被调用,其他元素的析构函数未被调用。
- 内存释放不完整,可能导致内存泄漏或程序崩溃。
3. 错误用法(混用 new
和 delete[]
)
int main() {
MyClass* obj = new MyClass; // 调用 1 次构造函数
delete[] obj; // 未定义行为:尝试释放未分配的内存
return 0;
}
可能的输出:
Constructed!
- 程序可能崩溃或产生不可预测的行为。
总结
new[]
和delete[]
必须配对使用,因为它们专门用于数组的内存管理。new
和delete
必须配对使用,因为它们专门用于单个对象的内存管理。- 混用会导致未定义行为,可能引发程序崩溃、内存泄漏或数据损坏。
这个问题考察的是对 C++ 内存管理机制的理解,尤其是 new[]
和 delete[]
的特殊行为。
THE END
暂无评论内容