我找到了 this one question asking the same thing ,但是只回答了"new"部分,所以又来了。
为什么删除操作符必须是静态的?不知何故,这没有意义。 new 运算符非常有意义,就像构造函数不能是虚拟的一样,new 运算符也不能。但是,当您使用继承时,析构函数可以(并且应该)是虚拟的,以便允许销毁(通过多态性)用作基类的对象。
我知道,当调用删除操作符时,对象已经被销毁,所以不存在“this”。然而,使用与虚拟析构函数相同的推理,让删除运算符匹配创建对象的新运算符仍然是有意义的。
这就是我的意思
class A
{
public:
virtual ~A() {}
};
class B : public A
{
public:
void* operator new (size_t sz);
void operator delete (void* ptr, size_t sz);
};
现在如果我们这样做
A *ptr = new B();
delete ptr; // <-- fail
应该调用 A 的删除操作符(默认),因为它是静态的,并且在编译时不知道(除了这里的简单情况)哪个删除操作符是正确的。
但是,我用上面的代码做了一个小测试程序(只是在 new/delete 运算符中使用 malloc/free,在 delete 中使用 print 语句),并使用 g++ 编译它。运行它出乎意料地在 B 的删除运算符中产生了输出。
我的(真正的)问题是:删除操作符是否存在某种隐含的“虚拟性”?它只是在没有这个指针的意义上是静态的吗?还是这只是一个 g++ 功能?
我开始查看 C++ 规范,但我必须承认,我对它有点不知所措,因此感谢任何帮助。
最佳答案
语言规则中的答案确实在 12.5 [class.free] 中。
如果您通过指向基类的指针进行删除,则析构函数必须是虚拟的,否则您将获得未定义的行为。否则,实现必须确定被删除对象的动态类型。
12.5/4 说,当 delete
没有以 ::
为前缀时,释放函数是通过查找 delete
来确定的动态类型的虚拟析构函数的上下文。这确保了类似虚拟的查找,即使 operator delete
始终是 static
成员函数。
原始分配和释放在概念上发生在对象的生命周期之外,因此在调用释放函数时,不再有对象提供虚拟查找机制,但查找规则确保 operator delete
具有动态(虚拟精简版!)查找机制。这意味着 operator delete 可以明智地是 static
而不会失去与原始对象的动态类型的联系。
关于c++ - 为什么删除操作符必须是静态的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2273187/