Потребление памяти указателем на вектор указателей - PullRequest
0 голосов
/ 21 марта 2012

Мне известно, что размер указателя фиксирован (а не размер данных, на которые он указывает).Теперь, учитывая, что, если у меня есть вектор данных в глобальной области видимости, и я объявляю указатель на вектор указателей на некоторые / все эти глобальные данные, сколько памяти это будет дополнительно использовать (ОЗУ)?Я в полном недоумении и буду признателен за некоторые идеи / советы.Я надеюсь, что дополнительное потребление памяти будет равно размеру вектора, умноженному на фиксированный размер указателя (скажем, 8 байт), независимо от сложности данных;поскольку данные, на которые он указывает, существуют в глобальном масштабе (т. е. новые данные не выделяются; надеюсь, я четко объяснил свои мысли).

Какой-то псевдокод, который выражает мой вопрос, будет выглядеть следующим образом:

std::vector<data> global_data;
std::vector<data*>* my_data = new std::vector<data*>();  //-Is this even valid? 
//-Now populate the vector with pointers to data in global_data
for(int i=0; i<global_data.size(); ++i) {
   my_data->push_back(&global_data[i]);
}

Тогда мой вопрос состоит в том, сколько дополнительной памяти в ОЗУ (т. Е. Превышает то, что уже используется при создании * 1006).* global_data ) используется m_data ??

Ответы [ 5 ]

6 голосов
/ 21 марта 2012

my_data будет занимать sizeof(std::vector<data*>*) байтов и не более sizeof(void*).

*my_data будет занимать sizeof(std::vector<data*>), что может быть всего лишь 3 * sizeof(data**), т.е. не более 3 * sizeof(void*).

*my_data будет управлять sizeof(data*) * my_data->capacity() байтами динамической памяти.


У меня есть серьезные сомнения, что эта информация будет полезна на практике.

2 голосов
/ 21 марта 2012

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

Однако вам определенно не следует делать это так, как вы делали в своем примере кода. Потому что std :: vector my меняет положение, в котором сохраняются ваши данные. Например. если вы push_back для новых объектов, ему в конечном итоге придется выделить новую память и скопировать данные во вновь выделенное пространство, поскольку это гарантирует, что пространство данных будет продолжаться. Затем он освободит память, использованную ранее. Тогда ваши старые указатели будут указывать на пространство, которое больше не используется вашей программой, вызывая ошибки сегментации, если вы попытаетесь их использовать.

1 голос
/ 21 марта 2012

Потребление памяти вектором близко к тому, что вы догадались.Вы правы, что размер вектора не будет зависеть от макета data.

Что касается фактического расчета общего размера вектора, то есть две части, которые вносят вклад:

  1. Сам фактический векторный объект.Вектор имеет некоторую внутреннюю структуру, например, он имеет указатель на свой внутренний массив.Также все его поля выровнены по определенным значениям.Общий размер любого вектора (включая выравнивание) можно найти с помощью sizeof(vector<data*>).На моей машине это дает 24

  2. Размер внутреннего массива.Это , а не на основе size() вектора, но фактически зависит от capacity() вектора.Общий размер будет my_data->capacitiy() * sizeof(data*).Я полагаю, что между элементами массива нет заполнения, но если таковые имеются, это также необходимо учитывать.

Общее потребление памяти будет тогда просто суммой # 1 и #2.

1 голос
/ 21 марта 2012

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

Вы в основном правы.Для любой разумной реализации std::vector базовое хранилище для std::vector<T> - это просто компактный массив T.В этом случае ваш T - это тип указателя data *, а не data.

. Для эффективного расширения может существовать некоторая дополнительная память, иначе каждая операция push_back должна будет увеличивать массив.(Взгляните на функции reserve и capacity std::vector.)

И, конечно, есть небольшие накладные расходы для выделения самого векторного объекта.

1 голос
/ 21 марта 2012

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

  • Количество элементов в векторе * размер каждого (т.е. размер указателя).
  • Плюс некоторые дополнительные«емкость» в векторе, который он использует, чтобы избежать постоянного изменения размера (возможно, некоторого небольшого постоянного фактора размера, и вы можете запросить его, вызвав емкость ()).
  • Плюс детали реализации вектора, которыенапример, три указателя (начало, конец, начало + емкость).

Если вы хотите выразить это в C ++, вы можете сделать что-то вроде этого:

sizeof(vector<data*>) + my_data.capacity() * sizeof(data*);

Примечаниечто это просто дает вам приблизительное предположение и игнорирует более сложные фрагменты, например, требуется ли больше «ОЗУ» для фактического отображения памяти, которую вы используете в пространстве приложения, и поведение стандартного распределителя в вашей системе и т. д.Но что касается C ++ и виртуальной памяти, я думаю, что это разумное приближение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...