Как сжать, чтобы соответствовать std :: vector эффективным способом памяти? - PullRequest
8 голосов
/ 23 апреля 2010

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

template< typename T, class Allocator >
void shrink_capacity(std::vector<T,Allocator>& v)
{
   std::vector<T,Allocator>(v.begin(),v.end()).swap(v);
}

Весь смысл сжатия - подогнать память, но этот метод сначала не создает глубокоескопировать, а затем обменять экземпляры?Таким образом, в какой-то момент - когда копия построена - использование памяти удваивается?

Если это так, есть ли более удобный для памяти метод сжатия?(В моем случае вектор действительно велик, и я не могу позволить себе одновременно хранить и оригинал, и его копию в памяти.)

Ответы [ 2 ]

3 голосов
/ 23 апреля 2010

Ну, если бы вы хотели изменить размер массива, что бы вы сделали? Вы должны создать новое и скопировать все значения поверх - будь то индивидуально или с помощью memcpy или чего-то еще. Вы не можете изменить размер массива в C или C ++.

std::vector в значительной степени гарантированно будет реализован с использованием массива для его хранения (IIRC, стандарт не гарантирует, что это массив, но массив - это единственное, что может удовлетворить различные требования API, такие как насколько эффективной должна быть каждая операция, так что, в действительности, она гарантирована, даже если эта гарантия не является явной). Поскольку он реализован с использованием массива, и вы не можете изменять размеры массивов без копирования, вы не можете изменять размеры векторов без копирования.

Теоретически вы могли бы иметь функцию shrink_capacity(), которая скрывала бы тот факт, что вам пришлось временно более или менее удвоить требования к размеру, но поскольку std::vector в настоящее время не имеет такой функции, вы должны фактически явная копия. Трюк со свопом - просто хороший способ сделать это.

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

0 голосов
/ 23 апреля 2010

Если ваш новый размер составляет половину исходного размера, вы можете избежать размещения нового вектора (или массива dynaimc, если вектор не может этого сделать) в неиспользованную конечную часть вашего старого.Не уверен, что вектор хранит информацию в этой области памяти, так что это было бы очень странно и страшно.Но это идея.

Теперь, когда я думаю об этом, операция типа memMove (), где вы копируете информацию в обратном порядке из последнего индекса, использованного в оригинале, в конец неиспользуемой области в оригинале, сохранит данные.Если вы сделали это размещением нового массива, вы могли бы указать его там, где новые данные существовали бы в середине исходной области памяти.Перемещение на месте само по себе.

...