Удаление полиморфного класса через контекст
От: 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
    }
Re[5]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Erop Россия  
Дата: 05.10.13 19:02
Оценка:
Здравствуйте, Molchalnik, Вы писали:

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


Ну, предположим, что пользователь захочет это всё проделать не с наследником твоего интерфейса, а со своим собственным классом, никак с твоим Фреймворком не связанным.
Как он это будет, по твоему делать, и, почему, в случае, если он выведется из твоего IObjecta, при условии, что у того будет виртуальный деструктор, этот его способ перестанет работать?..

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

M>Это "как-то" очень интересно. Подскажешь пару вариантов?


Ну это уже очень зависит от целей и задач пользователя твоего Фреймворка.
Например, если ему плевать, на выравнивание большее, чем выравнивание указателя, то он может сделать так:
struct IHeap {
    virtual void* Alloc( size_t ) = 0;
    virtual void Free( void* ) = 0;

    // Нулевой аллокатор трактуем, как дефолтный.
    static void* AllocAt( size_t size, IHeap* at = 0 ) 
        { return at ? at->Alloc( size ) : ::operator new( size ); }
    static void FreeAt( void* block, IHeap* at = 0 )
    {
        if( at )
            at->Free( block );
        else
            ::operator delete( block );
    }
};

struct AllocateOnHeap {
    void* operator new( size_t size, IHeap* heap = 0 )
    {
        IHeap** res = (IHeap**) IHeap::AllocAt( size + sizeof( IHeap* ), heap );
        if( res )
            *res++ = heap;
        return res;
    }
    void operator delete( void* block, IHeap* heap ) 
    { 
        if( block )
            IHeap::FreeAt( -1 + (IHeap**)block, heap ); 
    }
    void operator delete( void* block )
    { 
        if( block )
            operator delete( block, -1[(IHeap**)block] ); 
    }

    void* operator new[]( size_t size, IHeap* heap = 0 ) 
        { return operator new( size, heap ); }
    void operator delete[]( void* block, IHeap* heap ) 
        { operator delete( block, heap ); }
    void operator delete[]( void* block ) 
        { operator delete( block ); }
};
и выводить свои классы с хитрым аллокатором из AllocateOnHeap...

В результате, при аллокации их по new, можно будет указать кучу, примерно так:
class MyClass : public AllocateOnHeap {
};

delete new( getMyHeap() ) MyClass;


Только это, IMHO, не твоя печаль...
Или ты чего-то не договариваешь
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Molchalnik  
Дата: 08.10.13 05:41
Оценка:
Здравствуйте, Кодт, Вы писали:

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


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


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


честно — погуглил, прочитав у тебя

К>В принципе, shared_ptr — это и красиво, и сиплюсплюсно, и с приведением типов, — но с оверхедом.


Ну, я не в восторге от необходимости плодить лишние сущности — мне нужен, например, класс очереди без блокировок, но чтобы его использовать, я должен заводить ещё один непонятный объект, обращаться к искомому через сложные конструкции вроде Ptr.GetValue(), и всё это, без сомнения, сиплюсплюсно, но это не комплимент моему любимому с++ )))

а если без теории... то контекст/аллокатор должен работать и с контейнерами, которые а-приори интенсивно самостоятельно работают с памятью. Т.е. если некий умный указатель хранит ссылку на аллокатор, выделяет память для контейнера, то контейнеру придётся хранить ссылку на указатель либо на аллокатор, чтобы выделять память под свои элементы, а это уже какой-то ненужный оверхед... Впрочем, ты уже сказал об оверхеде)))

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

Я тоже так думал, см. пост выше. Вопрос именно в том, какой компромисс с совестью лучше — похерить арифметику указателей, добавив в выделение памяти лишний скрытый указатель на аллокатор, обращаться к объекту через указатель, или удалять объект через виртуальную obj.DeleteMe(). или по указателю угадывать, к какой он куче относится.

К>Всё равно информация об аллокаторе у тебя вынесена вовне — определяется не классом, а клиентским кодом. Зачем-то...

Кодт, если у тебя есть предложения по более грамотной архитектуре, это круто, буду рад

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


К>(Никогда не играл в симбиан или pugixml? вот там народ развлекался с неповторимыми способами передачи контекста).

Не играл)))

К>Вообще, борьба за изоляцию аллокаторов — это последний рубеж оптимизации. Когда ты точно знаешь, что именно многопоточное пользование общей кучей является узким местом в программе, и/или когда слишком жёстко встала проблема совместной работы нескольких плагинов (DLL) со статически прилинкованными и поэтому разными менеджерами кучи.

К>Так что смотри — не устраиваешь ли ты сейчас преждевременную оптимизацию, о которой говорил Дейкстра?

Я не имею большого опыта многопоточности, а опыта конкурентного программирования вообще не имею, но мне казалось, что раздельные кучи для потоков — это здорово, потому что:
1) поток упал — ты его перезапустил, и юзер ничего не заметил
2) у тебя баг с памятью в потоке — мемори лик — и ты его легко нашёл, благодаря замене всего одного указателя на аллокатор/контекст
3) дополнительная возможность мониторить
4) ты думал, тебе не нужны раздельные кучи, а когда они всё же понадобились, пришлось неделю с матами искать все new и delete в коде и заменять их на


void * НеведомыйМетодСозданияОбъектаСПомощьюВнешнегоАллокатораИ100500Прибамбас(HeapСтранныйКласс & heap,...)
void НеведомыйМетодУдаленияОбъектаСПомощьюВнешнегоАллокатораИ100500Прибамбас(void * ptr, HeapСтранныйКласс & heap,...)


Ну и причина No. 5 — я вообще экспериментирую с архитектурным шаблоном, передавая при создании в любой класс юзердата, например, содержащий ссылку на аллокатор, но в принципе, это может быть любая информация. Экспериментирую в поисках исключительно программисткого просветления. Однажды я сделал статический полиморфизм, и через полгода из-за нововведений сверху он "не покатил", и я задумался, есть ли что-то неизменное в программистком мире, и начал исследования... Ой, а почему вы в белых халатах? а куда вы меня тащите? ААААА... отпустите ме...
Re[7]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Кодт Россия  
Дата: 08.10.13 08:22
Оценка: 3 (1)
Здравствуйте, Molchalnik, Вы писали:

M>Ну, я не в восторге от необходимости плодить лишние сущности — мне нужен, например, класс очереди без блокировок, но чтобы его использовать, я должен заводить ещё один непонятный объект, обращаться к искомому через сложные конструкции вроде Ptr.GetValue(), и всё это, без сомнения, сиплюсплюсно, но это не комплимент моему любимому с++ )))


Во-первых, нахаляву ни lock-free, ни даже спрятанный за критическую секцию объект не получится.
В любом случае хоть синтаксически, да напишешь что-нибудь лишнее. Ну там
ATOMIC{ myQueue.push(x) }
atomic(myQueue).push(x);

Лучшее, что можно сделать — это написать фасадные функции, прячущие всю механику с глаз
myQueue.atomic_push(x);


Во-вторых, у shared_ptr синтаксис обычного указателя, и в большинстве случаев не надо писать ptr.get() — если только не заниматься хаками с передачей голых указателей там, где есть неголые.
Тотальное пересаживание на умные указатели и голые ссылки — решает.
А главное, что дальнейшая замена типа указателя (вместо shared использовать intrusive или любые другие, рукодельные) — пройдёт с минимальной кровью.

M>а если без теории... то контекст/аллокатор должен работать и с контейнерами, которые а-приори интенсивно самостоятельно работают с памятью. Т.е. если некий умный указатель хранит ссылку на аллокатор, выделяет память для контейнера, то контейнеру придётся хранить ссылку на указатель либо на аллокатор, чтобы выделять память под свои элементы, а это уже какой-то ненужный оверхед... Впрочем, ты уже сказал об оверхеде)))


Ты действительно пишешь интенсивно работающую программу? Если нет, то не парься загодя. Если да — подумай о том, нельзя ли вообще избавиться от динамического выделения памяти.
Паттерн flyweight, большие массивы заранее размещённых объектов и никакого "обычного" управления через new/delete, — только через свои функции.

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

M>Я тоже так думал, см. пост выше. Вопрос именно в том, какой компромисс с совестью лучше — похерить арифметику указателей, добавив в выделение памяти лишний скрытый указатель на аллокатор, обращаться к объекту через указатель, или удалять объект через виртуальную obj.DeleteMe(). или по указателю угадывать, к какой он куче относится.

Арифметика указателей для одиночных объектов не нужна — смело похерь её.
А с массивами разговор отдельный.

К>>Всё равно информация об аллокаторе у тебя вынесена вовне — определяется не классом, а клиентским кодом. Зачем-то...

M>Кодт, если у тебя есть предложения по более грамотной архитектуре, это круто, буду рад

Абстрактную архитектуру разрабатывать — дело неблагодарное.
Единственное общее предложение — пересесть на shared_ptr, если только действительно не высоконагруженное приложение.


M>Я не имею большого опыта многопоточности, а опыта конкурентного программирования вообще не имею, но мне казалось, что раздельные кучи для потоков — это здорово, потому что:

M>1) поток упал — ты его перезапустил, и юзер ничего не заметил

Лучше до греха не доводить. Поток может иметь зацепки за реальный мир, помимо общей кучи.
К тому же, пусть ты со своим фреймворком работаешь с отдельной кучей. Но пользователь может вовсю использовать общую — строки там всякие, маленькие временные объекты, векторы-шмекторы.

M>2) у тебя баг с памятью в потоке — мемори лик — и ты его легко нашёл, благодаря замене всего одного указателя на аллокатор/контекст


Это да. Но здесь можно расщедриться на дебажную сборку с толстыми указателями.

M>3) дополнительная возможность мониторить

M>4) ты думал, тебе не нужны раздельные кучи, а когда они всё же понадобились, пришлось неделю с матами искать все new и delete в коде и заменять их на

Когда понадобились, то не остановился на полумерах по замене всех new-delete, а воплотил Flyweight.
Опять же, много голых new-delete как бы намекает на Си поверх С++...

M>Ну и причина No. 5 — я вообще экспериментирую с архитектурным шаблоном, передавая при создании в любой класс юзердата, например, содержащий ссылку на аллокатор, но в принципе, это может быть любая информация. Экспериментирую в поисках исключительно программисткого просветления. Однажды я сделал статический полиморфизм, и через полгода из-за нововведений сверху он "не покатил", и я задумался, есть ли что-то неизменное в программистком мире, и начал исследования... Ой, а почему вы в белых халатах? а куда вы меня тащите? ААААА... отпустите ме...



Если достичь не просветления, а просто чистоты рук, и убивать объекты только там же, где они созданы, — то вполне можно ограничиться потокоспецифичными синглетонами (thread local storage).
Каждому потоку свой аллокатор.
Владение объектами между потоками не передавать. А если передавать, то там возникнет потребность в синхронизации доступа к чужой куче, и почему бы её не возложить на специальный удалятор, указанный в shared_ptr.
Перекуём баги на фичи!
Re[8]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Molchalnik  
Дата: 08.10.13 09:42
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Лучшее, что можно сделать — это написать фасадные функции, прячущие всю механику с глаз

К>
К>myQueue.atomic_push(x);
К>

а ещё лучше — назвать их
myQueue.push_back(x)

, и никому не говорить, что они atomic, ибо это уже подробности реализации, упрятанные за интерфейс


К>Ты действительно пишешь интенсивно работающую программу?

50 на 50

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

К>Паттерн flyweight, большие массивы заранее размещённых объектов

буду много думать

К>и никакого "обычного" управления через new/delete, — только через свои функции.

ну это я завсегда, просто я думал эти функции хранить за интерфейсом чисто виртуального аллокатора/контекста

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

M>>Я тоже так думал, см. пост выше. Вопрос именно в том, какой компромисс с совестью лучше — похерить арифметику указателей, добавив в выделение памяти лишний скрытый указатель на аллокатор, обращаться к объекту через указатель, или удалять объект через виртуальную obj.DeleteMe(). или по указателю угадывать, к какой он куче относится.

К>Арифметика указателей для одиночных объектов не нужна — смело похерь её.

К>А с массивами разговор отдельный.

Запретить delete[] и operator[] для своих классов?

К>Абстрактную архитектуру разрабатывать — дело неблагодарное.

К>Единственное общее предложение — пересесть на shared_ptr, если только действительно не высоконагруженное приложение.
у меня просто условно-абстрактный интерфейс поинтера для всего. если нужно — хоть shared_ptr, хоть weak_ptr, хоть smart_ptr прячь за него...


К>Опять же, много голых new-delete как бы намекает на Си поверх С++...


я не успел пока наплодить много, не более 5 на большой код...
Оставил их потому, что хотел заменить функциями из аллокатора/контекста
Re[9]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Кодт Россия  
Дата: 08.10.13 19:06
Оценка:
Здравствуйте, Molchalnik, Вы писали:

К>>Лучшее, что можно сделать — это написать фасадные функции, прячущие всю механику с глаз

К>>
К>>myQueue.atomic_push(x);
К>>

M>а ещё лучше — назвать их
M>
M>myQueue.push_back(x)
M>

M>, и никому не говорить, что они atomic, ибо это уже подробности реализации, упрятанные за интерфейс

А это уже как сказать.
Если у тебя есть внешние гарантии отсутствия гонок в данном месте, то можно сэкономить время на неблокирующей версии функции.
Или, к примеру, у тебя групповая операция. Было бы эффективно сделать
myQueue.lock(); // todo использовать scoped lock
myQueue.push_back(x);
myQueue.push_back(y);
.....
myQueue.unlock();

// или так
auto lockedQueue = myQueue.locked();
lockedQueue.push_back(x);
lockedQueue.push_back(y);
.....

чем дёргать мьютекс на каждый чих.

К>>и никакого "обычного" управления через new/delete, — только через свои функции.

M>ну это я завсегда, просто я думал эти функции хранить за интерфейсом чисто виртуального аллокатора/контекста

Во фреймворке — проще всего сделать фабричные функции YourPointer<T> create<T>() и void destroy(YourPointer<T>), например.
Для первой версии — они будут реализованы по-простому, через new/delete, а потом хоть какую политику устроить.
И искать несложно, функции-то в одном месте определены, в отличие от прямых операций.

К>>Арифметика указателей для одиночных объектов не нужна — смело похерь её.

К>>А с массивами разговор отдельный.

M>Запретить delete[] и operator[] для своих классов?


Как вариант. Но для начала — просто воздерживаться от прямого конструирования массивов где попало.
Отдельный разговор состоит не в том, чтоб запретить, а в начать с того, как массивы используются.
Массивов же много разных. И разреженные, и полиморфные, и какие угодно. Голая адресная арифметика нечасто востребована, достаточно арифметики итераторов или нумерации.
Перекуём баги на фичи!
Re[6]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 25.12.15 18:58
Оценка:
Здравствуйте, enji, Вы писали:


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


I. Подскажите, пожалуйста, коллеги, какие есть аналоги кроме следующих:

1. boost::thread_specific_ptr
2. для С++ 11: thread_local, _Thread_local
3. для gcc: __thread
4. для posix: pthread_key
5. для msvc: __declspec(thread)
6. для win:TlsAlloc, TlsSetValue, TlsGetValue, TlsFree
7. для QT: QThreadStorage<T>

II. Нигде не ошибся?
Re: Удаление полиморфного класса через контекст
От: Ops Россия  
Дата: 25.12.15 20:40
Оценка: +1
Здравствуйте, Molchalnik, Вы писали:

M>жду помощи


Кто выделяет память, тот знает, как освобождать. Умные указатели со своим делетером — самое простое.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re: Удаление полиморфного класса через контекст
От: UA Украина  
Дата: 25.12.15 20:40
Оценка: :)
Здравствуйте, Molchalnik, Вы писали:

Если ты отдаешь клиенту твоего фреймворка указатель на интерфейс, то что может быть в итоге кроме вызова Release?
Re: Удаление полиморфного класса через контекст
От: ELazin http://rsdn.ru/forum/prj/6225353.1
Автор: ELazin
Дата: 26.10.15
Дата: 26.12.15 08:48
Оценка: +2
Здравствуйте, Molchalnik, Вы писали:

Я когда прочитал про "грамотный дизайн" — сразу неладное почувствовал, но потом увидел код, потом прочитал некоторые комментарии ...
Re[7]: Удаление полиморфного класса через контекст
От: BulatZiganshin  
Дата: 26.12.15 13:13
Оценка:
Здравствуйте, Molchalnik, Вы писали:

в boost есть даже библиотека flyweight — оно тебе не подойдёт?
Люди, я люблю вас! Будьте бдительны!!!
Re[7]: Удаление полиморфного класса через контекст
От: dolgop8791  
Дата: 28.12.15 10:16
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>I. Подскажите, пожалуйста, коллеги, какие есть аналоги кроме следующих:


Я думаю у каждой библиотеки, которая претендует на звание "взрослой" и "базовой" для с++ есть что-то подобное:

ACE — ACE_TSS
Poco — ThreadLocal
Re[2]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 01.01.16 20:00
Оценка:
Здравствуйте, ELazin, Вы писали:

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


EL>Я когда прочитал про "грамотный дизайн" — сразу неладное почувствовал, но потом увидел код, потом прочитал некоторые комментарии ...


Какие конкретно претензии? Оценки не интересны, интересна конструктивная критика.
Re[2]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 01.01.16 20:06
Оценка:
Здравствуйте, UA, Вы писали:

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


UA>Если ты отдаешь клиенту твоего фреймворка указатель на интерфейс, то что может быть в итоге кроме вызова Release?


ты это о чём?
Re[2]: Удаление полиморфного класса через контекст
От: Molchalnik  
Дата: 01.01.16 20:12
Оценка:
Здравствуйте, Ops, Вы писали:

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


M>>жду помощи


Ops>Кто выделяет память, тот знает, как освобождать. Умные указатели со своим делетером — самое простое.


Спасибо. Правда, Кодт предложил это в этой теме в 2013, но это не важно. Всё равно благодарю. Только тогда уж и свою фабрику, и запрет на создание, и запрет на удаление,в общем, долго мучатся с каждым классом.
Re[3]: Удаление полиморфного класса через контекст
От: Erop Россия  
Дата: 21.12.16 00:27
Оценка:
Здравствуйте, Molchalnik, Вы писали:

M>Спасибо. Правда, Кодт предложил это в этой теме в 2013, но это не важно. Всё равно благодарю. Только тогда уж и свою фабрику, и запрет на создание, и запрет на удаление,в общем, долго мучатся с каждым классом.


Можно обойтись запретами в базовом классе
Автор: Erop
Дата: 05.07.09

Правда деструктор получится запретить только RT.

(схема такая: в objectPlaceholder зводим operator delete в котором пишем assert)
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Мало, мало про это на собеседованиях спрашивают... ;)
От: push  
Дата: 26.12.16 12:24
Оценка:
Здравствуйте, Erop, Вы писали:


E>    void operator delete( void* block )
E>    { 
E>        if( block )
E>            operator delete( block, -1[(IHeap**)block] ); 
E>    }


Можно уточнить момент выше? Не понял, что происходит. Почему решили, что при таком вызове есть какой-то указатель перед блоком? Если он есть, то почему бы не использовать оператор выше, просто добавив значение по умолчанию для второго параметра?
Re[7]: Мало, мало про это на собеседованиях спрашивают... ;)
От: Erop Россия  
Дата: 26.12.16 14:01
Оценка:
Здравствуйте, push, Вы писали:

P>Можно уточнить момент выше? Не понял, что происходит. Почему решили, что при таком вызове есть какой-то указатель перед блоком?

Не помню уже о чём там речь, но, скорее всего указатель клался в парном к delete операторе new...

P>Если он есть, то почему бы не использовать оператор выше, просто добавив значение по умолчанию для второго параметра?


1) Зачем?
2) Где взять значение?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Мало, мало про это на собеседованиях спрашивают... ;)
От: push  
Дата: 26.12.16 14:51
Оценка:
Здравствуйте, Erop, Вы писали:

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


P>>Можно уточнить момент выше? Не понял, что происходит. Почему решили, что при таком вызове есть какой-то указатель перед блоком?

E>Не помню уже о чём там речь, но, скорее всего указатель клался в парном к delete операторе new...

Всё, разобрался, там просто парный new не написан. Вместо него используется new с дефолтным вторым параметром.
В общем этот delete можно удалить, а в том, что повыше второму параметру присвоить нулевое дефолтное значение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.