从重载运算符删除中调用成员函数?

发布于 2024-10-26 20:59:37 字数 641 浏览 0 评论 0原文

这篇关于 二进制兼容的 C++ 接口 的文章包含代码:

class Window {
public:
  // ...
  virtual void destroy() = 0;

  void operator delete(void* p) {
    if (p) {
      Window* w = static_cast<Window*>(p);
      w->destroy(); // VERY BAD IDEA
    }
  }
};

对我来说,这似乎是错误的:operator delete() 适用于原始内存,其预期目的是释放它。该对象的析构函数已经被调用,因此调用 destroy() 对“幻影”对象起作用(如果它起作用的话)。事实上:这就是为什么 operator delete() 采用 void* 而不是 Window* (在本例中)。

那么,这个设计是有缺陷的,对吧? (如果它是正确的,为什么它是正确的?)

This article on Binary-compatible C++ Interfaces contains the code:

class Window {
public:
  // ...
  virtual void destroy() = 0;

  void operator delete(void* p) {
    if (p) {
      Window* w = static_cast<Window*>(p);
      w->destroy(); // VERY BAD IDEA
    }
  }
};

To me, that seems wrong: operator delete() works on raw memory with the intended purpose to free it. The object's destructor has already been called, so calling destroy() works on a "phantom" object (if it works at all). Indeed: that's why operator delete() takes a void* and not a Window* (in this case).

So, the design is flawed, right? (If it is correct, why is it correct?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无人问我粥可暖 2024-11-02 20:59:37

我同意(假设 Window::destroy 不是静态成员函数):

3.8p1:T 类型的对象的生命周期在以下情况下结束: 如果 T 是具有非平凡析构函数的类类型,则析构函数调用开始,或者[...]

3.8p5: [...]在对象的生命周期结束后,在重用或释放该对象所占用的存储空间之前,任何指向该对象[...]所在存储位置的指针可以使用,但只能以有限的方式使用。 ...如果对象将是或曾经是非 POD 类类型,则程序具有未定义行为,如果: 指针用于访问非静态数据成员或调用非静态对象的成员函数,或 [...]

(强调我的)

I agree (assuming Window::destroy is not a static member function):

3.8p1: The lifetime of an object of type T ends when: if T is a class type with a non-trivial destructor, the destructor call starts, or [...]

3.8p5: [...] After the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object [...] was located may be used but only in limited ways. ... If the object will be or was of a non-POD class type, the program has undefined behavior if: the pointer is used to access a non-static data member or call a non-static member function of the object, or [...]

(emphasis mine)

盗琴音 2024-11-02 20:59:37

是的,该代码(如果标记为 C++)是非常错误的。

正如您所说,运算符 new 和 delete 处理原始内存,而不是对象。

然而,那篇文章涉及特定的编译器和特定的实现问题,因此可能在受限的上下文中代码可以工作...此外,MS 并不因他们对可移植 C++ 的关心程度而闻名(实际上相反),所以 可能这种糟糕的代码(或者在 2002 年)实际上不仅可以工作,而且甚至是一个合理的解决方案。

Yes, that code (if labelled C++) is very wrong.

Operator new and delete as you say handle raw memory, not objects.

That article however deals with specific compilers and specific implementation issues so may be that in that restricted context the code works... moreover MS isn't exactly well renowned for how nicely they care about portable C++ (au contraire, indeed) so may be that kind of bad code is (or was in 2002) actually not only working but even a reasonable solution.

小耗子 2024-11-02 20:59:37

这是真正令人讨厌的代码,试图提供帮助。

文章指出,在 COM 代码中不应删除对象,而应调用obj->destroy()。因此,为了“有帮助”,作者让operator delete 执行销毁调用。可恶的!

更好的方法是只声明一个私有操作符delete,这样用户就无法删除对象,而必须找出正确的方法。

That is really nasty code, trying to be helpful.

The article says that in COM code should not delete the object, but call obj->destroy() instead. So to be "helpful" the author makes operator delete do the destroy call. Nasty!

Much better would have been to just declare a private operator delete, so the user cannot delete objects and must instead figure out the correct way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文