2012-01-08 3 views
2

Lets мы имеем,Размер станд :: массива, станд :: вектор и необработанного массива

std::array <int,5> STDarr; 
std::vector <int> VEC(5); 
int RAWarr[5]; 

Я попытался их размер, как,

std::cout << sizeof(STDarr) + sizeof(int) * STDarr.max_size() << std::endl; 
std::cout << sizeof(VEC) + sizeof(int) * VEC.capacity() << std::endl; 
std::cout << sizeof(RAWarr) << std::endl; 

Выходы,

40 
20 
40 

Правильно ли эти вычисления? Учитывая, что у меня недостаточно памяти для std::vector и нет возможности избежать динамического выделения, что мне использовать? Если бы я знал, что std::array приводит к снижению потребности в памяти, я мог бы изменить программу, чтобы сделать массив статическим.

+0

Не могли бы вы провести тот же эксперимент с контейнерами разного размера, например, 6? – dasblinkenlight

+0

Изменяя все 5s до 6s, ответьте: '48',' 44', '24' для STDarr, VEC, RAWarr соответственно. – Shibli

+0

Вы обеспокоены размером статического накладного расхода или дополнительным размером на элемент? –

ответ

3

Эти цифры неверны. Более того, я не думаю, что они представляют то, что, по вашему мнению, они представляют. Позволь мне объяснить.

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

size_t sizeof_int = sizeof(RAWarr)/5; // => sizeof(int) == 8 

, потому что это по существу определение sizeof(T): это число байтов между началом двух смежных объектов типа T в массиве , Это бывает непоследовательный с номером print for STDarr: шаблон класса std::array<T, n> указан в массиве n объектов типа T, встроенных в него. Кроме того, std::array<T, n>::max_size() является константным выражением, дающим n. То есть, мы имеем:

40            // is identical to 
sizeof(STDarr) + sizeof(int) * STDarr.max_size() // is bigger or equal to 
sizeof(RAWarr) + sizeof_int * 5     // is identical to 
40    + 40        // is identical to 
80 

Это 40 >= 80 - это contradication.

, подобным образом, то второе вычисление также не согласуется с третьим вычислению: std::vector<int> имеет по крайней мере 5 элементов и capacity() должен быть больше, чем чем size(). Кроме того, размер std::vector<int> не равен нулю. То есть, следующий всегда должен быть правдой:

sizeof(RAWarr) < sizeof(VEC) + sizeof(int) * VEC.capacity() 

Во всяком случае, все это в значительной степени не имеет отношения к то, что кажется ваш фактический вопрос быть: Что такое накладные расходы, представляющий n объекты типа T используя встроенную в массиве T, a std::array<T, n> и std::vector<T>? Ответ на этот вопрос:

  1. Встроенный массив T[n] использует sizeof(T) * n.
  2. std::array<T, n> использует тот же размер, что и T[n].
  3. A std::vector<T>(n) нуждается в контрольных данных (размер, емкость и, возможно, и, возможно, распределитель) плюс, по крайней мере, 'n * sizeof (T)' байты для представления его фактических данных. Он может также выбрать capacity(), который больше n.

В дополнение к этим номерам, на самом деле, используя любую из этих структур данных может потребовать добавления памяти:

  1. Все объекты выравниваются по соответствующему адресу. Для этого может быть дополнительный байт перед объектом.
  2. Когда объект выделен в куче, система управления памятью my включает пару байтов в дополнение к памяти, доступной. Это может быть просто слово с размером, но может быть, что-то вроде механизма выделения. Кроме того, эта память может жить где-то в другом месте, чем память распределения, например. где-то в хеш-таблице.

ОК, я надеюсь, что это обеспечило некоторую проницательность. Однако, здесь возникает важный сообщение : если std::vector<T> не способна удерживать объем данных у вас есть есть две ситуации:

  1. У вас есть очень мало памяти и большая часть этой дискуссии бесполезно, потому что вам нужно совершенно разные подходы, чтобы справиться с несколькими байтами, которые у вас есть. Это будет иметь место, если вы работаете с встроенными системами с ограниченными ресурсами.
  2. У вас слишком много данных, а использование T[n] или std::array<T, n> не поможет, потому что накладные расходы, о которых мы говорим, обычно составляют менее 32 байт.

Возможно, вы опишете то, что вы на самом деле пытаетесь сделать, и почему std::vector<T> не является вариантом.

+0

Я использовал необработанные массивы в своем коде, но он работал правильно. Я, конечно, потому, что это были необработанные массивы, я попробовал std :: vector, чтобы убедиться, что проблема связана с необработанными массивами. Однако он выбрал bad_alloc. Я не понимаю; если у меня есть 30 000 ints, выделенных как для std :: vector, так и для raw-массива, будет ли дополнительное использование памяти std :: vector в порядке байтов больше, чем для необработанного массива? – Shibli

+0

Обычно 'std :: vector (n)' выделяет 'm' с' n <= m' объектами типа 'T'. Точный 'm' не указан, но в целом я ожидал бы, что он не будет больше, чем' 2 * n', за исключением очень маленького 'n' (например, минимальная емкость может быть 16). То есть существуют 'm * sizeof (T)' байты, выделенные для фактических элементов. Кроме того, 'std :: vector ' потребуется в общей сложности до четырех указателей, чтобы указать начало, конец, емкость и распределитель плюс размер распределителя (если он нужен для любого размера). Как ваш код мог получить 30 000 элементов? –

+0

Вышеприведенный предполагает размер 8 байтов для int, что крайне редко.Я еще не сталкивался с системой, которая имеет такую ​​модель памяти. Как правило, int будет 4 байта или меньше, что, скорее всего, указывает на исходный вопрос (т. Е. Выстраивает строки с выходами из его sizeof()). – Vitali