重载具有特定参数的delete[]运算符

overload delete[] operator with specific arguments

本文关键字:delete 运算符 参数 重载      更新时间:2023-10-16

我们试图用特定的参数重载delete[]运算符。哪种说法正确?我们使用GNU编译器,并获得所有这些示例的编译器错误:

#include<memory>
using namespace std;
typedef unsigned int P;
struct A{
    static allocator<A>m;
    P p;
    void*operator new[](size_t s){return m.allocate(s);}
    void operator delete[](void*p,int s){m.deallocate((A*)p,s);}
    void operator delete[](void*p,size_t t,int s){m.deallocate((A*)p,s);}
};
int main(){
    A*a=new A[10];
    //delete (5) []a;       //expected ',' before 'a'
    //delete[5]a;           //expected ';' before ']' token
    //delete[] (5) a;       //type ‘int’ argument given to ‘delete’, expected
    //delete[]a (5);        //a’ cannot be used as a function
    //delete[]((int)5)a;    //type ‘int’ argument given to ‘delete’, expected pointer
    //delete[]a((int)5);    //‘a’ cannot be used as a function
    return 0;
}

这种位置删除器没有"语法糖"
只有当placementnew调用的构造函数抛出异常时,才会调用placementdeleter(如您所声明的)
然后程序将调用匹配的放置deleter(相同的签名),并尝试释放自定义分配的内存。

如果你仍然想调用这个方法,你必须手动调用操作员:

A::operator delete[](a, 5);

这里有一个很好的例子说明它是如何工作的:http://en.cppreference.com/w/cpp/memory/new/operator_delete

注意类析构函数中的异常(在触发异常后调用delete运算符):

#include <stdexcept>
#include <iostream>
struct X {
    X() { throw std::runtime_error(""); }
    // custom placement new
    static void* operator new(std::size_t sz, bool b) {
        std::cout << "custom placement new called, b = " << b << 'n';
        return ::operator new(sz);
    }
    // custom placement delete
    static void operator delete(void* ptr, bool b)
    {
        std::cout << "custom placement delete called, b = " << b << 'n';
        ::operator delete(ptr);
    }
};
int main() {
   try {
     X* p1 = new (true) X;
   } catch(const std::exception&) { }
}

TL;DR:只有当对象的构造函数抛出时,才会调用自定义放置删除程序,并且如果没有显式运算符调用(例如),则无法调用该删除程序

Class::operator delete[](a, 10, etc..);

无论如何都不会调用析构函数NOT(另一项您必须手动完成的任务)。


详细信息:

来自cppreference

运算符delete和运算符delete[]的重载(带附加用户定义的参数("放置表单",版本11-12)可以是像往常一样在全局范围内声明,并由匹配如果对象的构造函数正在被分配,引发异常。

标准库位置操作员删除(9-10)的表单无法替换,只能如果placement new表达式未使用::new,则进行自定义语法,通过提供具有匹配签名:void T::运算符delete(void*,void*)或voidT: :operator delete[](void*,void*)。

struct A{
    void* operator new[](std::size_t s){
        cout << "allocation 1" << endl;
        ...
        return ptr;
        }
    void* operator new[](std::size_t s, int){
        cout << "allocation 2" << endl;
        ...
        return ptr;
        }
    void operator delete[](void* s, std::size_t ){
        cout << "deallocate 1" << endl;
        ...
    }
    void operator delete[](void* s, std::size_t , int ){
        cout << "deallocate 2" << endl;
        ...
    }
};
int main(){
    A*a=new A[10];
    delete[] a;
    A*b=new(5) A[10];
    A::operator delete[](b,sizeof(b)/sizeof(A*),5); // You'll have to call it manually!
    return 0;
}