(C ++ 14) Перегрузить новый оператор, чтобы выделить больше непрерывного пространства, чем размер объекта - PullRequest
1 голос
/ 03 октября 2019

Класс (C ++ 14) ниже имеет перегруженный оператор new для выделения непрерывной памяти для объекта и некоторых байтов в качестве дополнительного хранилища. Объект хранит размер дополнительного хранилища в переменной-члене. Размер дополнительного хранилища должен быть передан в качестве параметра оператору new. Например, чтобы выделить 10 байтов в качестве хранилища:

Storage* ptr = new(10)Storage;

Приведенная ниже реализация приводит к ошибке: « выражение нового размещения относится к функции без размещения »:

class Storage
{
private:
    std::size_t storage_size;
public:
    Storage(){};
    ~Storage() {};
    static void* operator new(std::size_t object_size, std::size_t storage_size)
    {
        // Allocate memory for the object and the storage
        char* ptr = new char[object_size + storage_size];
        // Placement new
        Storage* ptr2 = ::new(ptr)Storage;
        // Set member variable
        ptr2->storage_size = storage_size;
        // Return 
        return ptr2;
    }
    static void operator delete(void* ptr, std::size_t storage_size)
    {
        // How?
    }
};

Как мне реализовать перегруженный оператор delete?

ОБНОВЛЕНИЕ

Следующий код основан на комментариях и примере @Igor Tandetnik (спасибо!) И работает, как и ожидалось. Я мог бы также установить переменную-член.

class Storage
{
private:
    std::size_t storage_size;
public:
    Storage(bool do_throw) { 
        std::cout << "Storage(): this = " << this << std::endl; 
        if (do_throw) {
            std::cout << "Throwing exception!" << std::endl;
            throw 42;
        }
    };
    ~Storage() { std::cout << "~Storage(): this = " << this << std::endl; };
    void print_storage() { std::cout << "Storage size: " << storage_size << std::endl; }
    static void* operator new(std::size_t object_size, std::size_t storage_size)
    {
        char* ptr = new char[object_size + storage_size]; // Allocate memory
        std::cout << "Overloaded new: ptr = " << static_cast<void*>(ptr) << std::endl;
        Storage* ptr2 = static_cast<Storage*>(static_cast<void*>(ptr));
        ptr2->storage_size = storage_size;
        return ptr;
    }
    static void operator delete(void* ptr, std::size_t storage_size)
    {
        std::cout << "Overloaded delete: ptr = " << ptr << std::endl;
        delete[] ptr;
    }
    static void operator delete(void* ptr)
    {
        std::cout << "Delete: ptr = " << ptr << std::endl;
        delete[] ptr; // Destructor called automatically
    }
};


int main()
{
    try {
        auto ptr = new(10) Storage(false);
        ptr->print_storage();
        delete ptr;

        ptr = new(10) Storage(true);
        ptr->print_storage();
        delete ptr;
    }
    catch (...) {
        std::cout << "Got exception" << std::endl;
    }

    return 0;
}
...