Как работать с контейнером STL с элементами классов, содержащих большие массивы данных - PullRequest
0 голосов
/ 24 января 2011

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

Проблема в том, что мне нужно реализовать конструктор копирования и ... ну .. я не хочу делать глубокую копию (так как это занимает слишком много времени, поэтому я придерживаюсь мелкой копии), но потом снова У меня есть проблема, не зная, когда удалять массив данных в деструкторе (поскольку я вызываю деструктор дважды и получаю данные только один раз, плюс первый вызов деструктора, вероятно, происходит из-за вставки / перемещения элемента в контейнере поэтому мне все еще нужны данные массива на этом этапе).

Я думал об использовании интеллектуальных указателей, таких как std :: shared_ptr, для массива данных, но из того, что я прочитал, они не вызывают delete [], а скорее delete - что является позором, поскольку у меня есть обычный массив [].

Прямо сейчас у меня есть решение, которое вручную вызывает функцию «DeleteArray» для класса перед удалением его из контейнера. Это прекрасно работает, но .. это не приятно.

Есть идеи?

Ответы [ 6 ]

3 голосов
/ 24 января 2011

Boost имеет класс shared_array, который похож на shared_ptr, но будет использовать delete[], или вы можете добавить пользовательское средство удаления к shared_ptr, которое вызовет delete[].

1 голос
/ 24 января 2011

Еще лучшим решением было бы положить shared_ptr s ваших больших объектов в контейнеры и избегать дорогих копий вместе.

Редактировать 0:

Другой вариант, конечно, состоит в том, чтобы сделать сами объекты легкими и копируемыми с помощью shared_array. как полагает Иеремия.

1 голос
/ 24 января 2011

Не используйте массив, используйте вместо него std::vector.Затем укажите на это с помощью умного указателя.

0 голосов
/ 24 января 2011

Большое спасибо за все ваши проницательные ответы!

Это напоминает мне, почему в прошлый раз, когда у меня была эта проблема, я вручную кодировал очередь, не копируя себя.Не могу сказать, что это заняло у меня намного больше времени, чем понимание того, как сделать красивую, чистую версию.:)

Итак .. что я сделал:

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

Решение б) Я поместил массив в еще один класс и использовал для этого smartpointer (shared_ptr)учебный класс.Работал действительно приятно.Мне пришлось использовать shared_ptr s как элементы вектора.(Сначала я не думал об этом.)

Решение c) Использование shared_ptr для хранения массива.Как оказалось, идея довольно плохая, так как она вызывает delete вместо delete [], вам нужно предоставить свой собственный deleteter и каким-то образом возникли другие (синтаксические) проблемы, поэтому мне потребовалось что-то вроде 2h +, чтобы найти это решение.

В заголовочном файле это выглядит примерно так:

 template< typename T >
  struct
array_deleter
  {
      void
    operator ()( T const * p)
      { delete[] p; }
  };

class MemoryStressChunk
{
private:
    int chunkSizeInValues;
    std::shared_ptr< __int64 > data;
};

и в файле кода:

data.reset(
    new __int64[chunkSizeInValues], 
    array_deleter< __int64 >() );

, и чтобы его использовать, я должен снова его вывести:

__int64 *d = data.get();

В следующий раз я мог бы настоятельно рассмотреть возможность использования буст-версий.У меня не было наддува на моей машине, поэтому для меня это не вариант.

Я так понимаю Решение d) будет использовать вектор классов, содержащий shared_ptr s, для вектора (вместо этого).массива).После всего того, что я имел с c), я не делал этого на вершине.:)

Если кто-то хочет взглянуть на код, вы можете получить его здесь http://andreas -reiff.de / wp-content / uploads / 2011/01 / Tool-MemTester.zip.Осторожно, возможно, в версии a) есть утечка памяти (используйте shared_ptr для класса, как в версии b)).

Спасибо за вашу помощь еще раз!

0 голосов
/ 24 января 2011

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

0 голосов
/ 24 января 2011

Для массивов существует эквивалент shared_ptr, по крайней мере, в библиотеках Boost.Он называется shared_array и ведет себя точно так, как вы ожидаете.Проверьте спецификацию в http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_array.htm?sess=8940ad57baa307d68cb2e7fd2939d2db.

...