gpt4 book ai didi

c++ - C++20 中的 "destroying operator delete"是什么?

转载 作者:行者123 更新时间:2023-12-04 04:26:35 25 4
gpt4 key购买 nike

C++20 引入了“破坏 operator delete ”:operator delete 的新重载采用标签类型 std::destroying_delete_t 范围。
这到底是什么,什么时候有用?

最佳答案

在 C++20 之前,对象的析构函数总是在调用它们的 operator delete 之前调用。 .与破坏operator delete在 C++20 中,operator delete可以改为调用析构函数本身。这是一个非常简单的非破坏与破坏的玩具示例operator delete :

#include <iostream>
#include <new>

struct Foo {
~Foo() {
std::cout << "In Foo::~Foo()\n";
}

void operator delete(void *p) {
std::cout << "In Foo::operator delete(void *)\n";
::operator delete(p);
}
};

struct Bar {
~Bar() {
std::cout << "In Bar::~Bar()\n";
}

void operator delete(Bar *p, std::destroying_delete_t) {
std::cout << "In Bar::operator delete(Bar *, std::destroying_delete_t)\n";
p->~Bar();
::operator delete(p);
}
};

int main() {
delete new Foo;
delete new Bar;
}
和输出:
In Foo::~Foo()
In Foo::operator delete(void *)
In Bar::operator delete(Bar *, std::destroying_delete_t)
In Bar::~Bar()
关于它的关键事实:
  • 一个毁灭operator delete函数必须是类成员函数。
  • 如果不止一个 operator delete是可用的,一个破坏性的总是优先于非破坏性的。
  • 不销毁和销毁签名的区别operator delete是前者收到 void * , 后者接收一个指向被删除对象类型的指针和一个虚拟 std::destroying_delete_t范围。
  • 喜欢不破坏operator delete , 破坏 operator delete也可以选择 std::size_t和/或 std::align_val_t参数,同理。这些意味着他们一直做的同样的事情,他们追求假人std::destroying_delete_t范围。
  • 在销毁 operator delete 之前不调用析构函数运行,因此预计它自己会这样做。这也意味着该对象仍然有效并且可以在这样做之前进行检查。
  • 具有非破坏性 operator delete , 调用delete在派生对象上通过指向没有虚拟析构函数的基类的指针是未定义的行为。这可以通过给基类一个破坏性的 operator delete 来变得安全和明确。 ,因为它的实现可以使用其他方式来确定要调用的正确析构函数。

  • 销毁用例 operator deleteP0722R1 中有详细说明.这是一个快速的总结:
  • 破坏operator delete允许在其末尾具有可变大小数据的类保留大小 delete 的性能优势.这是通过将大小存储在对象中并在 operator delete 中检索它来实现的。在调用析构函数之前。
  • 如果一个类将有子类,那么同时分配的任何可变大小的数据都必须在对象的开始之前,而不是在结束之后。在这种情况下,唯一安全的 delete这样的物体正在摧毁operator delete ,从而可以确定分配的正确起始地址。
  • 如果一个类只有几个子类,它可以通过这种方式为析构函数实现自己的动态调度,而不需要使用 vtable。这会稍微快一些,并导致更小的类(class)规模。

  • 这是第三个用例的示例:
    #include <iostream>
    #include <new>

    struct Shape {
    const enum Kinds {
    TRIANGLE,
    SQUARE
    } kind;

    Shape(Kinds k) : kind(k) {}

    ~Shape() {
    std::cout << "In Shape::~Shape()\n";
    }

    void operator delete(Shape *, std::destroying_delete_t);
    };

    struct Triangle : Shape {
    Triangle() : Shape(TRIANGLE) {}

    ~Triangle() {
    std::cout << "In Triangle::~Triangle()\n";
    }
    };

    struct Square : Shape {
    Square() : Shape(SQUARE) {}

    ~Square() {
    std::cout << "In Square::~Square()\n";
    }
    };

    void Shape::operator delete(Shape *p, std::destroying_delete_t) {
    switch(p->kind) {
    case TRIANGLE:
    static_cast<Triangle *>(p)->~Triangle();
    break;
    case SQUARE:
    static_cast<Square *>(p)->~Square();
    }
    ::operator delete(p);
    }

    int main() {
    Shape *p = new Triangle;
    delete p;
    p = new Square;
    delete p;
    }
    它打印这个:
    In Triangle::~Triangle()
    In Shape::~Shape()
    In Square::~Square()
    In Shape::~Shape()
    (注意:GCC 11.1 和更早版本在启用优化时会错误地调用 Triangle::~Triangle() 而不是 Square::~Square()。参见 comment 2 of bug #91859。)

    关于c++ - C++20 中的 "destroying operator delete"是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67595789/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com