是否在 new[] 运算符未定义行为分配的内存上调用 delete 运算符?
Is calling delete operator on a memory allocated by new[] operator undefined behavior?
我非常确定它是,但如果我正确解释标准(第 18.6.1.2 节 new.delete.array)提到:
void operator delete[](void* ptr) noexcept;
pointer.
. 13 Default behavior: Calls operator delete(ptr)
既然在默认行为中 delete[] 只是调用它的 delete(ptr) 等价物,为什么调用哪个版本很重要?
我尝试使用示例代码来验证这一点,但它崩溃了,这使得 new[] 和 delete 不匹配确实导致了不好的事情变得更加明显
#include <iostream>
#include <memory>
class foo{
public:
void bar(){
std::cout << "foo's bar" << std::endl;
}
~foo(){
std::cout << "foo dies after this" << std::endl;
}
};
int main() {
std::shared_ptr<foo> x(new foo[10]);
return 0;
}
应如何解释上述引用的标准行?
您将 delete[]
表达式与函数 operator delete[]
混淆了。当你写:
delete[] p;
然后编译器发出代码,为 p
指向的数组中的所有对象调用析构函数,然后使用参数 p
调用释放函数 operator delete[]
。根据您引用的文档,默认 ::operator delete[]
调用 ::operator delete
。因此,当使用默认实现时,以下对释放函数的调用是等效的:
::operator delete[] (p);
::operator delete(p);
但是以下 不是 等价的,因为它们所做的不仅仅是调用释放函数:
delete[] p;
delete p;
我非常确定它是,但如果我正确解释标准(第 18.6.1.2 节 new.delete.array)提到:
void operator delete[](void* ptr) noexcept; pointer.
. 13 Default behavior: Calls operator delete(ptr)
既然在默认行为中 delete[] 只是调用它的 delete(ptr) 等价物,为什么调用哪个版本很重要? 我尝试使用示例代码来验证这一点,但它崩溃了,这使得 new[] 和 delete 不匹配确实导致了不好的事情变得更加明显
#include <iostream>
#include <memory>
class foo{
public:
void bar(){
std::cout << "foo's bar" << std::endl;
}
~foo(){
std::cout << "foo dies after this" << std::endl;
}
};
int main() {
std::shared_ptr<foo> x(new foo[10]);
return 0;
}
应如何解释上述引用的标准行?
您将 delete[]
表达式与函数 operator delete[]
混淆了。当你写:
delete[] p;
然后编译器发出代码,为 p
指向的数组中的所有对象调用析构函数,然后使用参数 p
调用释放函数 operator delete[]
。根据您引用的文档,默认 ::operator delete[]
调用 ::operator delete
。因此,当使用默认实现时,以下对释放函数的调用是等效的:
::operator delete[] (p);
::operator delete(p);
但是以下 不是 等价的,因为它们所做的不仅仅是调用释放函数:
delete[] p;
delete p;