Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 04.10.13 13:13
Оценка:
Доброго времени суток, коллеги!!!

Такой нетиповой вопрос.

Есть сложная иерархия классов, наследуемых от одного чисто виртуального предка. Дерево наследования — произвольное, но сначала идут интерфейсы, а последний потомок любого дерева — имплементация. Имплементация содержит ссылку на кучу heap, или класс, который содержит в себе функции new и delete (будем называть их контекстом). Нужно удалить по ссылке на интерфейс имплементацию, но при этом удалить через контекст, в нужной куче или через нужные функции аллокации/деаллокации.

Примечание. Класс имеет право не пользоваться контекстом. Поэтому запихнуть ссылку на контекст в общий предок мы не можем. К тому же, если любой класс нашей системы будет иметь +4 или +8 байт на любой класс, даже инкапсулирующий int, это всё же значительная нагрузка на память.

У меня есть в голове несколько вариантов, жду ваших и критики моих. Есть чёткая цель — наиболее грамотный дизайн.

мои варианты:

1) Скрытый член класса. переопределить new как-то так

class Object {
 public:
  virtual ~Object() = 0;
};

inline Object::~Object() {}

class HeapInterface {
 public:
  virtual void * Allocate(size_t number_bytes) = 0;
  virtual void   Deallocate (void * ptr) = 0;
  virtual ~HeapInterface() {}
};

class Ansector1 : public Object {
 public:
  virtual ~Ansector1() {}
  void* operator new (std::size_t size) {assert(0);return 0;}
  void* operator new (std::size_t size, HeapInterface * context) {
    const size_t kPtrSize = sizeof (HeapInterface*);
    void * block = context -> Allocate(size+kPtrSize);
    Ansector1 * ret = reinterpret_cast<Ansector1*>(static_cast<char *>(block) + kPtrSize);
    HeapInterface ** heap_ptr = static_cast<HeapInterface **>(block);
    heap_ptr[0] = context;
    return ret;
  }
  void operator delete (void* ptr) {
    HeapInterface * heap_value = static_cast<HeapInterface**>(ptr)[-1];
    heap_value->Deallocate(static_cast<HeapInterface**>(ptr)-1);
  }
  HeapInterface * heap() {return reinterpret_cast<HeapInterface **>(this)[-1];}
  void set_heap (HeapInterface * value) {reinterpret_cast<HeapInterface **>(this)[-1] = value;}

  /*
   * Недостатки:
   *  1) нельзя использовать со стандартными контейнерами
   *  2) непрозрачность извне (напишет кто-то перебор массива таких элементов с помощью указателей... и никогда не поймёт, где ошибка)
   *  3) нерабочая арифметика указателей
   */
};


2) Грязный хак в delete


class Ansector2 : public Object {
 public:
  Ansector2(HeapInterface * context_value) : heap_(context_value) {}
  virtual ~Ansector2() {}
  void operator delete (void* ptr) {
    HeapInterface * heap_value = static_cast<Ansector2*>(ptr)->heap(); // грязный хак - обращение к члену класса после вызова деструктора класса
    heap_value->Deallocate(ptr);
  }
  HeapInterface * heap() {return heap_;}
  void set_heap (HeapInterface * value) {heap_ = value;}

 private:
  HeapInterface * heap_;

  /*
   * Недостатки:
   *  1) использование грязного хака
   */
};


3) Удаление через спецфункцию (с запретом на new и delete)

class Object3 {
  public:
  virtual void SelfDestruct() = 0;
   virtual ~Object3() = 0;
};
inline Object3::~Object3() {}

class Ansector3 : public Object3 {
 public:
  Ansector3(HeapInterface * context_value) : heap_(context_value) {}
  HeapInterface * heap() {return heap_;}
  void set_heap (HeapInterface * value) {heap_ = value;}
  virtual void SelfDestruct() {SelfDestruct(this);}

 protected:
  void operator delete (void* ptr) {} //ничего не делает. защищён, чтобы нельзя напрямую было вызывать Ansector3::new и Ansector3::delete
  static Ansector3 * Create() {/* некий кодД */} //new использовать невозможно, но можно сделать фабричный метод (дофантазируйте его определение сами)

 private:
  static void SelfDestruct(Ansector3 * self) {
    HeapInterface * heap_value = self->heap();
    self->~Object3();
    heap_value->Deallocate(self);
  }
  HeapInterface * heap_;
/*
 * Недостатки:
 * 1)удаление только через функцию
 * 2)невозможность использовать некоторые стандартные фишки - например, стандартные умные указатели из разных библиотек, придётся писать свои
 */
};


4) глобальный Map, связывающий адрес объекта и контекст. Функция delete по адресу объекта находит в глобальной мапе адрес объекта контекста и через него удаляет объект.

Недостатки:
1) потеря скорости удаления за счёт доступа к Map'у
2) увеличенная нагрузка на память


жду помощи, нужна самая грамотная архитектура из возможных, отдельно рассматриваются варианты на чистом c++98 и на c++11
Re: Удаление полиморфного класса через контекст
От: enji  
Дата: 04.10.13 13:31
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>Доброго времени суток, коллеги!!!


M>Такой нетиповой вопрос.


M>Есть сложная иерархия классов, наследуемых от одного чисто виртуального предка. Дерево наследования — произвольное, но сначала идут интерфейсы, а последний потомок любого дерева — имплементация. Имплементация содержит ссылку на кучу heap, или класс, который содержит в себе функции new и delete (будем называть их контекстом). Нужно удалить по ссылке на интерфейс имплементацию, но при этом удалить через контекст, в нужной куче или через нужные функции аллокации/деаллокации.


Посмотрев твой код, я так и не понял — ты в момент удаления знаешь тип? Или удаляешь по указателю на Object?

Если первое — то заводишь свои new / delete

Если второе — то определенный для наследников delete тебе не поможет, нужен delete для Object, которому придется узнавать, как аллоцирован объект — в стандартном хипе или твоем собственном. Ну к примеру заведи в Object еще одну виртуальную функцию.

А вообще наиболее правильный вариант, имхо, вместо "чистых" указателей и new/delete использовать unique_ptr или shared_ptr. Оба позволяют сохранять делетеры и дергают их при удалении.

Таким образом ты отвяжешь способ удаления от типа и сможешь один и тот же тип создавать как в обычной куче, так и в твоей собственной.
Re: Удаление полиморфного класса через контекст
От: Кодт Россия  
Дата: 04.10.13 13:51
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>Есть сложная иерархия классов, наследуемых от одного чисто виртуального предка. Дерево наследования — произвольное, но сначала идут интерфейсы, а последний потомок любого дерева — имплементация. Имплементация содержит ссылку на кучу heap, или класс, который содержит в себе функции new и delete (будем называть их контекстом). Нужно удалить по ссылке на интерфейс имплементацию, но при этом удалить через контекст, в нужной куче или через нужные функции аллокации/деаллокации.


M>Примечание. Класс имеет право не пользоваться контекстом. Поэтому запихнуть ссылку на контекст в общий предок мы не можем. К тому же, если любой класс нашей системы будет иметь +4 или +8 байт на любой класс, даже инкапсулирующий int, это всё же значительная нагрузка на память.


Сперва нужно ответить на 3 вопроса.
1. Зачем нужно много разных аллокаторов.
2. Кто отвечает за выбор аллокатора (финальный класс и его фабрика, каждый объект индивидуально, вызывающая сторона).
3. Сколько аллокаторов в системе.

Забегая сильно вперёд, могу предложить такой ход. Если аллокаторов мало, они глобальные, и адреса их куч не перехлёстываются, то определить принадлежность указателя куче — очень просто.
Перекуём баги на фичи!
Re[2]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 04.10.13 14:06
Оценка:
E>Посмотрев твой код, я так и не понял — ты в момент удаления знаешь тип? Или удаляешь по указателю на Object?

может быть и так, и так, или например так:

class XxxInterface : public Object{};

class Xxx : public XxxInterface {};

/*
...
некий код
*/

XxxInterface * p = Xxx::Create();
/*
...
некий код
*/

delete p; //или p->SelfDestruct(); в одной из архитектур



E>Если второе — то определенный для наследников delete тебе не поможет, нужен delete для Object, которому придется узнавать, как аллоцирован объект — в стандартном хипе или твоем собственном. Ну к примеру заведи в Object еще одну виртуальную функцию.


Как ты представляешь вызов виртуальной функции из delete? С учётом, что delete вызывается уже после деструктора. Надеятся на то, что таблица виртуальных функций после деструктора жива, ты не имеешь права (хотя что с ней будет?)

E>А вообще наиболее правильный вариант, имхо, вместо "чистых" указателей и new/delete использовать unique_ptr или shared_ptr. Оба позволяют сохранять делетеры и дергают их при удалении.


E>Таким образом ты отвяжешь способ удаления от типа и сможешь один и тот же тип создавать как в обычной куче, так и в твоей собственной.


Интересный вариант, спасибо



----------------------------

Ещё идеи?
Re[2]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 04.10.13 14:21
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Molchalnik, Вы писали:


M>>Есть сложная иерархия классов, наследуемых от одного чисто виртуального предка. Дерево наследования — произвольное, но сначала идут интерфейсы, а последний потомок любого дерева — имплементация. Имплементация содержит ссылку на кучу heap, или класс, который содержит в себе функции new и delete (будем называть их контекстом). Нужно удалить по ссылке на интерфейс имплементацию, но при этом удалить через контекст, в нужной куче или через нужные функции аллокации/деаллокации.


M>>Примечание. Класс имеет право не пользоваться контекстом. Поэтому запихнуть ссылку на контекст в общий предок мы не можем. К тому же, если любой класс нашей системы будет иметь +4 или +8 байт на любой класс, даже инкапсулирующий int, это всё же значительная нагрузка на память.


К>Сперва нужно ответить на 3 вопроса.

К>1. Зачем нужно много разных аллокаторов.

Теоретически, я пишу свой фреймворк и я не знаю, как извернётся пользователь фреймворка и как использует возможность задавать свой аллокатор каждому объекту.
Практически — я хочу сделать несколько потоков и каждому прописать свою кучу. Что логично. Но это на текущий момент, может, потом мне это станет не нужно или появятся новые потребности. Обычно, если есть инструмент — то под него появляются задачи. Даже если изначально инструмент был нафиг не нужен.

К>2. Кто отвечает за выбор аллокатора (финальный класс и его фабрика, каждый объект индивидуально, вызывающая сторона).


вызывающая сторона для каждого объекта индивидуально.

К>3. Сколько аллокаторов в системе.


для моих текущих целей — немного, равно числу потоков, т.е. все аллокаторы можно засунуть в вектор

К>Забегая сильно вперёд, могу предложить такой ход. Если аллокаторов мало, они глобальные, и адреса их куч не перехлёстываются, то определить принадлежность указателя куче — очень просто.


Перебором куч? Если так, то это вариант ассоциативного массива(map'а), только реализация чуть другая, специфичная. Но экономия памяти налицо, тоже отличная идея. Если куча удваивает объём аллоцированных данных (когда распределяемая память закончилась), то мы имеем скорость доступа порядка NlogM, где M — средний объём памяти, аллоцированная кучей, а N — число куч.
Re[3]: Удаление полиморфного класса через контекст
От: enji  
Дата: 04.10.13 15:28
Оценка:
Здравствуйте, Molchalnik, Вы писали:

E>>Если второе — то определенный для наследников delete тебе не поможет, нужен delete для Object, которому придется узнавать, как аллоцирован объект — в стандартном хипе или твоем собственном. Ну к примеру заведи в Object еще одну виртуальную функцию.


M>Как ты представляешь вызов виртуальной функции из delete? С учётом, что delete вызывается уже после деструктора. Надеятся на то, что таблица виртуальных функций после деструктора жива, ты не имеешь права (хотя что с ней будет?)


Да, тут я что-то не подумал
Re[3]: Удаление полиморфного класса через контекст
От: enji  
Дата: 04.10.13 15:30
Оценка:
Здравствуйте, Molchalnik, Вы писали:

К>>Забегая сильно вперёд, могу предложить такой ход. Если аллокаторов мало, они глобальные, и адреса их куч не перехлёстываются, то определить принадлежность указателя куче — очень просто.


M>Перебором куч? Если так, то это вариант ассоциативного массива(map'а), только реализация чуть другая, специфичная. Но экономия памяти налицо, тоже отличная идея. Если куча удваивает объём аллоцированных данных (когда распределяемая память закончилась), то мы имеем скорость доступа порядка NlogM, где M — средний объём памяти, аллоцированная кучей, а N — число куч.


Ну если ты вызываешь delete из того же потока, где создал объект (что вообще говоря желательно) то аллокатор ему известен
Re[4]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 04.10.13 16:35
Оценка:
Здравствуйте, enji, Вы писали:

E>Здравствуйте, Molchalnik, Вы писали:


К>>>Забегая сильно вперёд, могу предложить такой ход. Если аллокаторов мало, они глобальные, и адреса их куч не перехлёстываются, то определить принадлежность указателя куче — очень просто.


M>>Перебором куч? Если так, то это вариант ассоциативного массива(map'а), только реализация чуть другая, специфичная. Но экономия памяти налицо, тоже отличная идея. Если куча удваивает объём аллоцированных данных (когда распределяемая память закончилась), то мы имеем скорость доступа порядка NlogM, где M — средний объём памяти, аллоцированная кучей, а N — число куч.


E>Ну если ты вызываешь delete из того же потока, где создал объект (что вообще говоря желательно) то аллокатор ему известен


Откуда? я вот не могу сообразить.
Re[5]: Удаление полиморфного класса через контекст
От: enji  
Дата: 04.10.13 17:15
Оценка:
Здравствуйте, Molchalnik, Вы писали:

E>>Ну если ты вызываешь delete из того же потока, где создал объект (что вообще говоря желательно) то аллокатор ему известен


M>Откуда? я вот не могу сообразить.


Пихаешь аллокатор в boost::thread_specific_ptr или аналог
Re[3]: Удаление полиморфного класса через контекст
От: Erop Россия  
Дата: 04.10.13 18:13
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>Как ты представляешь вызов виртуальной функции из delete? С учётом, что delete вызывается уже после деструктора. Надеятся на то, что таблица виртуальных функций после деструктора жива, ты не имеешь права (хотя что с ней будет?)


Как это что? Её затрут указателем на таблицу предка жешь...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Мало, мало про это на собеседованиях спрашивают... ;)
От: Erop Россия  
Дата: 04.10.13 18:19
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>Есть сложная иерархия классов, наследуемых от одного чисто виртуального предка. Дерево наследования — произвольное, но сначала идут интерфейсы, а последний потомок любого дерева — имплементация. Имплементация содержит ссылку на кучу heap, или класс, который содержит в себе функции new и delete (будем называть их контекстом). Нужно удалить по ссылке на интерфейс имплементацию, но при этом удалить через контекст, в нужной куче или через нужные функции аллокации/деаллокации.


1) Заводишь в имплементации свои собственные operator delete и operator new, которые фигачат так, как надо.

2) В самой верхней базе заводишь *ВНИМАНИЕ* — виртуальный деструктор!!!

3) Ходят слухи, что С++ гарантирует, что при разрушении объекта через полиморфный указатель, позовётся operator delete для MDT, если подумаешь, поймёшь, что иначе быть могло бы вряд ли

4) Возможно это не решит твои проблемы, но сведёт их к обычным проблемам с аллокаторами, так как сложность иерархии станет не важна
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 05.10.13 05:17
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Molchalnik, Вы писали:


M>>Как ты представляешь вызов виртуальной функции из delete? С учётом, что delete вызывается уже после деструктора. Надеятся на то, что таблица виртуальных функций после деструктора жива, ты не имеешь права (хотя что с ней будет?)


E>Как это что? Её затрут указателем на таблицу предка жешь...


Для чего?
Re[6]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 05.10.13 05:17
Оценка:
Здравствуйте, enji, Вы писали:
E>>>Ну если ты вызываешь delete из того же потока, где создал объект (что вообще говоря желательно) то аллокатор ему известен

M>>Откуда? я вот не могу сообразить.


E>Пихаешь аллокатор в boost::thread_specific_ptr или аналог


тоже вариант... но если человек не планировал использовать буст, то ему целый буст ради этой штуки надо будет за собой тащить...
Re[2]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Molchalnik  
Дата: 05.10.13 05:27
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) Заводишь в имплементации свои собственные operator delete и operator new, которые фигачат так, как надо.


E>2) В самой верхней базе заводишь *ВНИМАНИЕ* — виртуальный деструктор!!!


E>3) Ходят слухи, что С++ гарантирует, что при разрушении объекта через полиморфный указатель, позовётся operator delete для MDT, если подумаешь, поймёшь, что иначе быть могло бы вряд ли


E>4) Возможно это не решит твои проблемы, но сведёт их к обычным проблемам с аллокаторами, так как сложность иерархии станет не важна


Егор, прошу прощения, если я не прав, но мне показалось, что ты просто невнимательно прочитал вопрос, это так?

1. Проблема, как ты верно заметил, не в иерархии, а именно в аллокаторах/кучах/контекстах
2. Если бы я не знал про " *ВНИМАНИЕ* — виртуальный деструктор!!!" — я бы такой вопрос не смог бы задать. Проблема сложнее и глубже, чем то, о чём "на собеседованиях спрашивают"
3. "это не решит твои проблемы, но сведёт их к обычным проблемам с аллокаторами" — каким образом? вот вызвался нужный delete, и что? каким образом ты получишь адрес аллокатора? Весь вопрос в том, как свести проблему "к обычным аллокаторам"
4. What is MDT?

Ещё раз повторяю, проблема не в каких-то элементарных знаниях, о которых ты нам напомнил, я это оставил за кадром, потому что это и так очевидно. Если посмотришь на мой код, там все твои замечания по умолчанию учтены. Проблема в том, что пользователь при создании объекта может задать свои new и delete и свою кучу. вопрос, как это сделать? Желательно и прямым методом, и красивым. Использовать/написать указатель, который бы хранил информацию о сих предметов, например, прямой метод, но некрасивый, т.к. неудобный. Но зато очень в духе С++
Re[5]: Удаление полиморфного класса через контекст
От: Erop Россия  
Дата: 05.10.13 06:12
Оценка:
Здравствуйте, Molchalnik, Вы писали:

E>>Как это что? Её затрут указателем на таблицу предка жешь...


M>Для чего?


ну, как бы...
struct B { virtual void foo( int );}
struct D : B { 
    int z;
    void foo( int x ) { z = x; } 
};

void bar()
{
    D d;
    // Тут, когда будет работать деструктор B, как думаешь, какая версия foo вызовется и почему?..
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Erop Россия  
Дата: 05.10.13 06:17
Оценка:
Здравствуйте, Molchalnik, Вы писали:


M>4. What is MDT?

Самый выведенный тип.

M>Ещё раз повторяю, проблема не в каких-то элементарных знаниях, о которых ты нам напомнил, я это оставил за кадром, потому что это и так очевидно. Если посмотришь на мой код, там все твои замечания по умолчанию учтены. Проблема в том, что пользователь при создании объекта может задать свои new и delete и свою кучу.

НУ ты же вопрос задал про какие-то там иерархии, и про виртуальные методы, которые кучу вовзращают? А не так, что вот мол у меня есть куча аллокаторов, на них без всякой системы аллокируются объекты, и как мне их разрушать?..

Если вопрос стоит так, то обычно в блоке перед его началом сохраняют как-то инфу о том, что за аллокатор там был, или по диапазонам как-то мапируют, как вариант.


M>вопрос, как это сделать? Желательно и прямым методом, и красивым. Использовать/написать указатель, который бы хранил информацию о сих предметов, например, прямой метод, но некрасивый, т.к. неудобный. Но зато очень в духе С++


Если бы MDT умел всегда решать эту проблему, то диспечерезация operator delete через виртуальный деструктор решала бы все проблемы...
А так ты рассказал то ли слишком мало, то ли не то вообще, и ждёшь, что тебе помогут. Попробуй рассказать больше, может тебе удастся рассказать что-то такое, что кому-то подскажет решение твоей проблемы.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Molchalnik  
Дата: 05.10.13 08:19
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Molchalnik, Вы писали:



M>>4. What is MDT?

E>Самый выведенный тип.

M>>Ещё раз повторяю, проблема не в каких-то элементарных знаниях, о которых ты нам напомнил, я это оставил за кадром, потому что это и так очевидно. Если посмотришь на мой код, там все твои замечания по умолчанию учтены. Проблема в том, что пользователь при создании объекта может задать свои new и delete и свою кучу.

E>НУ ты же вопрос задал про какие-то там иерархии, и про виртуальные методы, которые кучу вовзращают? А не так, что вот мол у меня есть куча аллокаторов, на них без всякой системы аллокируются объекты, и как мне их разрушать?..

E>Если вопрос стоит так, то обычно в блоке перед его началом сохраняют как-то инфу о том, что за аллокатор там был, или по диапазонам как-то мапируют, как вариант.



M>>вопрос, как это сделать? Желательно и прямым методом, и красивым. Использовать/написать указатель, который бы хранил информацию о сих предметов, например, прямой метод, но некрасивый, т.к. неудобный. Но зато очень в духе С++


E>Если бы MDT умел всегда решать эту проблему, то диспечерезация operator delete через виртуальный деструктор решала бы все проблемы...

E>А так ты рассказал то ли слишком мало, то ли не то вообще, и ждёшь, что тебе помогут. Попробуй рассказать больше, может тебе удастся рассказать что-то такое, что кому-то подскажет решение твоей проблемы.

Я рассказал довольно много с помощью кода

Но если в двух словах, я делаю свой фреймворк для проекта. Ну и вообще для жизни. Проект может ВНЕЗАПНО стать многопоточным. Одна из идей фреймворка — "Пользователь при создании объекта может определять для него new,delete, и кучу. Объект может удалятся (естессно) через указатель на базовый класс"
Re[4]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Molchalnik  
Дата: 05.10.13 08:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>Если вопрос стоит так, то обычно в блоке перед его началом сохраняют как-то инфу о том, что за аллокатор там был


Это "как-то" очень интересно. Подскажешь пару вариантов?
Re[5]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Кодт Россия  
Дата: 05.10.13 10:12
Оценка: +1
Здравствуйте, Molchalnik, Вы писали:

M>Я рассказал довольно много с помощью кода


Знаешь про отмазку TL;DR? Знаешь, что первые две буквы в ней означают?

M>Но если в двух словах, я делаю свой фреймворк для проекта. Ну и вообще для жизни. Проект может ВНЕЗАПНО стать многопоточным. Одна из идей фреймворка — "Пользователь при создании объекта может определять для него new,delete, и кучу. Объект может удалятся (естессно) через указатель на базовый класс"


В принципе, shared_ptr — это и красиво, и сиплюсплюсно, и с приведением типов, — но с оверхедом.
Можно подумать о какой-то аналогичной штуковине. Отрезать от неё всё ненужное — подсчёт ссылок, например. Останется только пара (указатель на объект, указатель на аллокатор).

Всё равно информация об аллокаторе у тебя вынесена вовне — определяется не классом, а клиентским кодом. Зачем-то...
Так почему бы и не сделать на штатных неинтрузивных указателях. Опять же, понизишь порог вхождения в использование твоего фреймворка.
(Никогда не играл в симбиан или pugixml? вот там народ развлекался с неповторимыми способами передачи контекста).

Вообще, борьба за изоляцию аллокаторов — это последний рубеж оптимизации. Когда ты точно знаешь, что именно многопоточное пользование общей кучей является узким местом в программе, и/или когда слишком жёстко встала проблема совместной работы нескольких плагинов (DLL) со статически прилинкованными и поэтому разными менеджерами кучи.
Так что смотри — не устраиваешь ли ты сейчас преждевременную оптимизацию, о которой говорил Дейкстра?
Перекуём баги на фичи!
Re: Удаление полиморфного класса через контекст
От: anonymous185  
Дата: 05.10.13 10:25
Оценка:
5) виртуальная фунция для удаления объекта

class __declspec(novtable) Object 
{
public:
    virtual ~Object()
    {

    }
    virtual void Delete() = 0;
};

class Ansector1 : public Object 
{
    void Delete()
    {
        delete this;
    }

public:
    virtual ~Ansector1() {}
    
    void* operator new (size_t size) 
    {
        return LocalAlloc(0, size);//например
    }
    
    void operator delete (void* p) 
    {
        LocalFree(p);//например
    }
};

.....
    if (Object* po = new Ansector1)
    {
        po->Delete();// вызывается Ansector1::operator delete
    }
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.