C++ 实际销毁对象是否需要运算符delete的销毁形式?

C++ 实际销毁对象是否需要运算符delete的销毁形式?,c++,language-lawyer,c++20,delete-operator,C++,Language Lawyer,C++20,Delete Operator,C++20增加了运算符delete的销毁形式,其区别在于std::destroming_delete_t参数。它使delete表达式在调用操作符delete之前不再销毁对象 其目的是在显式调用对象的析构函数和释放内存之前,允许根据对象的状态定制删除 然而,我不清楚,在实现这样一个操作符时,我是否真的需要销毁这个对象。具体来说,我是否可以拥有一个静态对象池,并将它们分发给用户,这些用户随后可以将它们视为动态分配的对象?这样,在对象上执行的delete表达式只会将其返回到池中,而不会销毁它。例如,以

C++20增加了
运算符delete
的销毁形式,其区别在于
std::destroming_delete_t
参数。它使
delete
表达式在调用
操作符delete
之前不再销毁对象

其目的是在显式调用对象的析构函数和释放内存之前,允许根据对象的状态定制删除

然而,我不清楚,在实现这样一个操作符时,我是否真的需要销毁这个对象。具体来说,我是否可以拥有一个静态对象池,并将它们分发给用户,这些用户随后可以将它们视为动态分配的对象?这样,在对象上执行的
delete
表达式只会将其返回到池中,而不会销毁它。例如,以下程序是否定义良好

#include <new>
 
struct A {
    virtual ~A() = default;
};

// 'Regular' dynamically allocated objects
struct B : A {
    static A* create() {
        return new B();
    }

private:
    B() = default;
};

// Pooled, statically allocated objects
struct C : A {
    static A* create() {
        for (auto& c: pool) {
            if (!c.in_use) {
                c.in_use = true;
                return &c;
            }
        }
        throw std::bad_alloc();
    }

private:
    static C pool[3];

    bool in_use = false;

    C() = default;

    void operator delete(C *c, std::destroying_delete_t) {
        c->in_use = false;
    }
};

C C::pool[3];

// Delete them identically via the common interface.
void do_something_and_delete(A* a) {
    delete a;
}

int main() {
    do_something_and_delete(B::create());
    do_something_and_delete(B::create());
    do_something_and_delete(C::create());
    do_something_and_delete(C::create());
}
#包括
结构A{
virtual~A()=默认值;
};
//“常规”动态分配对象
结构B:A{
静态A*create(){
返回新的B();
}
私人:
B()=默认值;
};
//池化的、静态分配的对象
结构C:A{
静态A*create(){
用于(自动和控制:池){
如果(!c.正在使用){
c、 使用中=正确;
返回&c;
}
}
抛出std::bad_alloc();
}
私人:
静态C池[3];
bool in_use=false;
C()=默认值;
void操作符delete(C*C,std::destroming_delete_t){
c->in_use=false;
}
};
C::池[3];
//通过公共界面以相同方式删除它们。
void do_something_和_delete(A*A){
删除一条;
}
int main(){
做某事并删除(B::create());
做某事并删除(B::create());
做某事并删除(C::create());
做某事并删除(C::create());
}

按照定义,销毁删除运算符的目的是为了有效地处理创建和销毁对象的能力,这些对象的解除分配和销毁由于某种原因需要访问对象。它通过防止在使用销毁操作符delete函数对对象调用
delete
时自动调用对象的析构函数来实现这一点。然后将(仍然有效)对象传递给销毁操作符delete,以便它可以执行解除分配和销毁业务

其目的不是让语句
删除任何内容向用户谎报此语句完成的内容。但是,作为该功能的一个用例(没有
virtual
功能的虚拟析构函数)的结果,该功能可以(ab)用于欺骗用户

当对象的析构函数被输入时(或当存储被重用/释放时),对象的生存期结束。如果销毁运算符delete(ab)用于阻止调用该析构函数,则
delete
ing对象不会结束其生存期


但是对用户撒谎是个坏主意,你不应该这样做。

而覆盖常规
虚拟
函数并不是以完全相同的方式“撒谎”?用户不应该关心对象是否“真的”被破坏。从他们的角度来看,他们不允许在
删除任何内容之后取消对
任何内容的引用在任何情况下。这只是抽象。@yurikilochek:“重写常规虚拟函数不是以完全相同的方式“说谎”吗?”不是。通过声明函数
virtual
,您就是在声明重写它的意图。通过重写它,您声明了替换基类版本的意图。在所有情况下,所有相关方的意图都是明确的,当您做出
删除任何内容时,没有背信弃义
实际上并没有破坏
任何东西
@yurikilochek:“这只是抽象。”这是一个糟糕的抽象,它扭曲了显而易见的代码的含义,使之成为它不是的东西。如果您想要一个接口,在该接口中您可以暂时使用一个对象,然后返回该对象供以后使用,那么就创建该接口。不要仅仅因为技术上可行,就将
delete
重构到该机制中。如果您想将智能指针用于此类类型,可以提供将调用返回API的删除程序,而不是覆盖基本语法结构(如
delete
)的行为。此问题被标记为语言问题。答案花了很多时间在说教OP是否应该,而没有时间引用标准。这似乎不适合这样一个带标签的问题?如果它是合法的,它会说“是”,因为删除结束对象的生命周期是调用析构函数的(唯一)功能,所以我猜是这样的?@yakadamnevraumont:“没有时间引用标准”这是允许的,因为标准中没有禁止它的内容,你不能说没有什么东西是被禁止的。我的意思是,我可以复制/粘贴关于生命终结的部分,但我不认为这会对任何事情产生实质性影响。