使用特定参数重载delete []运算符

时间:2014-09-27 19:49:14

标签: c++ delete-operator

我们正在尝试使用特定参数重载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;
}

2 个答案:

答案 0 :(得分:4)

这种放置删除器没有“语法糖” 只有当一个由placement new调用的构造函数抛出异常时,才会调用一个放置删除器(就像你声明的那样)。 然后程序将调用匹配的放置删除器(相同的签名)并尝试释放自定义分配的内存。

如果您仍想调用此方法,则必须手动调用操作员:

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&) { }
}

答案 1 :(得分:2)

TL; DR :只有在对象的构造函数抛出且没有显式操作员调用时才能调用自定义放置删除器,例如。

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

无论如何,析构函数将 NOT 被调用(您必须自己手动完成另一项任务)。


详细说明:

来自cppreference

  

操作员删除和操作员删除[]的额外载荷   用户定义的参数(“放置形式”,版本11-12)可能是   像往常一样在全球范围内声明,并由匹配调用   如果是对象的构造函数,则放置新表达式的形式   被分配正在抛出异常。

     

标准库放置   操作员删除(9-10)的形式不能被替换,只能是   如果放置new-expression没有使用:: new,则自定义   语法,通过提供类特定的放置删除(17,18)   匹配签名:void T :: operator delete(void *,void *)或void   T :: 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;
}