Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как в перегруженный оператор delete


Автор: georain 29.1.2008, 22:05
Вот хочу создать базовый класс с перегруженными new и delete, всё отлично, только вот мне нужно в операторе delete знать размер удаляемого класса, чтобы передать менеджеру памяти (его суть как раз что он его не запоминает). Т.е. если удаляется производный класс то нужен соответственно размер производного класса. Вот такая реализация не компилится:

Код

class BasicContainer{
public:
    BasicContainer(){};
    virtual ~BasicContainer(){};

    void * operator new(size_t size){
        return const_cast<void *>(ContainerOperatorObject.new_container(size));
    };
    void operator delete(void * pointer){
        ContainerOperatorObject.delete_container(pointer, mysize());
    };

    //возвращает размер класса
    virtual size_t mysize(){sizeof(*this);};
};


ругаясь на строчку
Код

ContainerOperatorObject.delete_container(pointer, mysize());

а конкретно на mysize() : a nonstatic member reference must be relative to a specific object.

Во-первых я не понимаю что ему надо, а во-вторых такая реализация не блещет изяществом smile
В каждом производном классе придётся вставлять

Код

//возвращает размер класса
    virtual size_t mysize(){sizeof(*this);};


что не весело. Может кто подскажет как это по человечески сделать?

Автор: JackYF 29.1.2008, 22:15
Цитата(georain @  29.1.2008,  21:05 Найти цитируемый пост)
только вот мне нужно в операторе delete знать размер удаляемого класса, чтобы передать менеджеру памяти (его суть как раз что он его не запоминает)

Все известные мне менеджеры памяти сами знают размер удаляемого куска памяти. Иначе с полиморфизмом придётся туго.

Автор: georain 29.1.2008, 22:22
Цитата(georain @  29.1.2008,  22:05 Найти цитируемый пост)
его суть как раз что он его не запоминает
 (его - размер)
В этом и фишка, т.е. что никак чтоли? Если рассуждать логически, то все известные нам даны уже на этапе компиляции, нужно только их правильно использовать.
Почему же моя реализация не работает?

добавлено:
Я тут покопался, оказывается operator delete - статическая функция :( и что делать?

Автор: MAKCim 29.1.2008, 22:36
georain, 
Цитата(georain @  29.1.2008,  22:05 Найти цитируемый пост)
его суть как раз что он его не запоминает

плохо
что мешает сделать так
Код

void * operator new(size_t size){
        int * address = static_cast<int*>(const_cast<void *>(ContainerOperatorObject.new_container(size + sizeof(int))));
        *address = size;
        return address + 1;
};


Автор: georain 29.1.2008, 23:09
Это не подходит. Тут фишка в экономии памяти.
Ведь смотрите, если уж мы в каждом классе всё равно имеем издержки на указатель к виртуальной таблице, так почему бы нам не хранить размер каждого класса только в одном экземпляре. И при удалении по заданному адресу получать из этого же адреса и размер области (размер класса) через виртуальную функцию.
Пока писал понял как реализовать smile. Вроде... как всегда

Автор: georain 30.1.2008, 00:04
Я изменил интерфейс менеджера на
Код

    void operator delete(void * pointer){
        ContainerOperatorObject.delete_container(pointer);
    };

т.е. теперь он принимает только указатель, т.е.  operator delete остаётся статическим, а для определения размера я вызываю
Код

    size = ((BasicContainer *) pointer)->mysize();

уже изнутри менеджера.

Вуоля, пока на форуме не расписал всё, ничего понять не мог, что происходит.

Только теперь остаётся ещё одна интересная задачка:
в каждом наследуемом классе придётся писать функцию
Код

//возвращает размер класса
    virtual size_t mysize(){sizeof(*this);};

можно ли это обойти? ;)

Автор: JackYF 30.1.2008, 00:07
Цитата(georain @  29.1.2008,  23:04 Найти цитируемый пост)
 virtual size_t mysize(){sizeof(*this);};

зачем? не вижу необходимости

Автор: georain 30.1.2008, 00:19
Цитата(JackYF @  30.1.2008,  00:07 Найти цитируемый пост)
зачем? не вижу необходимости 

эээ... поясни пожалуйста  

или ты имеешь ввиду что и так нормально.
На самом деле да, это небольшие затраты, но ведь это повторение кода.
Абсолютно одинакового кода, неужели нет способов этого избежать (кроме #define smile).

Автор: Lazin 30.1.2008, 09:26
georain, сделай деструктор виртуальным, и ты сможешь получать размер оператором sizeof, ф-я mysize будет ненужна

Автор: Alek86 30.1.2008, 10:45
Цитата(georain @  30.1.2008,  00:04 Найти цитируемый пост)
в каждом наследуемом классе придётся писать функцию


придется, а что поделать? :(
при агрегации тоже часто куча копипаста

Автор: JackYF 30.1.2008, 15:13
Блин, ещё раз. Вы в памяти при создании объекта храните количество байт в этом объекте. Этот же размер использует delete, когда ему нужно удалить память. На фига вам mysize(), объясните мне?

Автор: archimed7592 30.1.2008, 17:38
Извините, что вклиниваюсь в вашу увлекательную беседу на тему "как сделать так, чтобы враг не догадался" smile, но, если изначальный вопрос ещё актуален, то ответ такой: добавить параметр типа size_t.
Код

struct A
{
    static void operator delete(void * pointer, size_t sz)
    { /* ... */ }

    static void operator delete [](void * pointer, size_t sz)
    { /* ... */ }
// ...
};

Автор: chipset 30.1.2008, 20:15
А нельзя delete на шаблонах сделать? Щаз компилера под руками нет.

Автор: archimed7592 31.1.2008, 00:52
Цитата(chipset @  30.1.2008,  20:15 Найти цитируемый пост)
А нельзя delete на шаблонах сделать? Щаз компилера под руками нет. 

Если ты про operator delete, то можно, но толку от такого оператора будет немного, ибо вызывать можно будет только явно.

Автор: georain 31.1.2008, 02:52
Цитата(JackYF @  30.1.2008,  15:13 Найти цитируемый пост)
На фига вам mysize(), объясните мне? 

Ответ прост: нам не нужно в каждом объекте хранить ещё одно поле, размер мы получаем статически.
(гигибайты оперативки медленно но верно делают свою дело smile)

Цитата(Lazin @  30.1.2008,  09:26 Найти цитируемый пост)
georain, сделай деструктор виртуальным, и ты сможешь получать размер оператором sizeof, ф-я mysize будет ненужна 

 smile 

Цитата(archimed7592 @  30.1.2008,  17:38 Найти цитируемый пост)
добавить параметр типа size_t.
Код

static void operator delete(void * pointer, size_t sz);


А вот и ответ на вопрос "Как в перегруженный оператор delete добавить размер класса"
Спасибо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)