Я делаю забавные вещи с размещением новых, и вещи терпят неудачу.Обходные? - PullRequest
1 голос
/ 18 июля 2010

У меня очень большой разбросанный класс, который по сути является очень надуманным двухмерным связанным списком. Я хочу иметь возможность «скомпилировать» его, под этим я подразумеваю, что хочу завершить список, чтобы можно было сделать только доступ для чтения, а затем переместить все элементы в смежные области памяти. Мое грубое решение таково:

#include <new>
...
MyListNode* pool = new MyListNode[length];
new(&pool[position]) MyListNode();

Проблема в том, что у меня по существу есть два класса, один из которых выделен новым, а другой - этим методом, и когда я пытаюсь удалить любой из объектов, выделенных вышеуказанным методом, glibc убивает программу из-за неверный указатель

Естественное решение состоит в том, чтобы создать два класса и просто использовать полиморфизм во время выполнения, чтобы обеспечить один интерфейс, но две реализации, и т. Д. Есть ли способ, которым стандарт памяти в C ++ допускает такого рода покерные игры?

Ответы [ 2 ]

3 голосов
/ 18 июля 2010

Очевидная возможность - проверить адрес объекта и удалить его только в том случае, если он находится за пределами вашего пула.Если бы я делал это, я бы, вероятно, перегрузил бы operator new для класса, и он всегда выделял бы пространство из вашего пула.Таким образом, вы получаете непрерывное выделение без копирования, и ваши объекты распределяются равномерно, поэтому вы также можете их равномерно удалять.

2 голосов
/ 18 июля 2010

Вы вызываете delete для одного из объектов в вашем массиве? Или вы вручную вызываете деструктор, чтобы отразить новое размещение?

Так как у вас есть один вызов для невнесения новых, вы должны иметь только один вызов для удаления. А так как у вас n вызовов для размещения новых, вы должны вручную вызвать деструктор n раз.

Итак, вы можете захотеть что-то вроде этого:

// Allocate an array of chars instead of an array of MyListNode.  Since we
// are going to use placement new, this is necessary if MyListNode has a
// a default constructor
MyListNode* pool = static_cast<MyListNode *>(new char[sizeof(MyListNode) * length);
for (size_t position = 0; position < length; ++position)
    new(&pool[position]) MyListNode();

...

for (position = 0; position < length; ++position)
    pool[position].~MyListNode()

delete[] static_cast<char *>(pool);
...