overload delete[] operator with specific arguments

倖福魔咒の 提交于 2019-12-11 03:21:50

问题


We're trying to overload the delete[] operator with specific arguments. Which is the right way to call it? We use the GNU compiler and obtain compiler errors with all of these samples:

#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;
}

回答1:


There's no "syntactic sugar" for this kind of placement deleter.
A placement deleter (like what you've declared) is only called when a constructor that was called by a placement new, throws an exception.
Then the program will call the matching placement deleter (same signature) and try to free the customly allocated memory.

If you still want to call this method, you'll have to call the operator manually:

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

There's a nice example of how it works here: http://en.cppreference.com/w/cpp/memory/new/operator_delete

Notice the exception in the class destructor (the delete operator is called after the exception is triggered):

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



回答2:


TL;DR: custom placement deleters are only called if a constructor of the object throws and can't be called without an explicit operator call e.g.

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

Destructors will NOT be called anyway (another task you'll have to do manually yourself).


Details:

From cppreference

Overloads of operator delete and operator delete[] with additional user-defined parameters ("placement forms", version 11-12) may be declared at global scope as usual, and are called by the matching placement forms of new-expressions if a constructor of the object that is being allocated throws an exception.

The standard library placement forms of operator delete (9-10) cannot be replaced and can only be customized if the placement new-expression did not use the ::new syntax, by providing a class-specific placement delete (17,18) with matching signature: void T::operator delete(void*, void*) or 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;
}


来源:https://stackoverflow.com/questions/26078560/overload-delete-operator-with-specific-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!