Есть два ограничения, оба не навязанные C ++, а аппаратными средствами.
Первый предел (никогда не должен быть достигнут) устанавливается ограничениями типа размера, используемого для описания индекса в массиве (и его размера). Это определяется максимальным значением, которое std::size_t
может принять система. Этот тип данных достаточно большой, чтобы содержать размер в байтах любого объекта.
Другой предел - это предел физической памяти. Чем больше ваши объекты в массиве, тем быстрее будет достигнут этот предел, поскольку память заполнена. Например, a vector<int>
данного размера n обычно занимает в несколько раз больше памяти, чем массив типа vector<char>
(минус небольшое постоянное значение), поскольку int
обычно больше, чем char
. Следовательно, a vector<char>
может содержать больше элементов, чем vector<int>
до заполнения памяти. То же самое относится и к необработанным массивам в стиле C, таким как int[]
и char[]
.
Кроме того, этот верхний предел может зависеть от типа, allocator
используемого для построения, vector
потому что allocator
он свободен для управления памятью любым удобным для него способом. Очень странный, но, тем не менее, мыслимый распределитель может объединять память таким образом, чтобы идентичные экземпляры объекта совместно использовали ресурсы. Таким образом, вы можете вставить много идентичных объектов в контейнер, который в противном случае использовал бы всю доступную память.
Кроме того, C ++ не устанавливает никаких ограничений.
new
илиmalloc
. Часть памяти, большая чем массив, может быть доступна через указатель.Никто не упомянул ограничение размера стекового фрейма .
Память может быть выделена в двух местах:
Ограничение размера здесь представляет собой комбинацию доступного оборудования и способности ОС имитировать пространство с помощью других устройств для временного хранения неиспользуемых данных ( т.е. перемещения страниц на жесткий диск).
Ограничение размера здесь определяется компилятором (с возможными аппаратными ограничениями). Если вы читаете документацию компилятора, вы часто можете настроить этот размер.
Таким образом, если вы выделяете массив динамически (ограничение велико и подробно описано в других публикациях.
В качестве альтернативы, если массив размещен в стеке, вы ограничены размером кадра стека. NB векторы и другие контейнеры имеют небольшое присутствие в стеке, но обычно большая часть данных будет в куче.
источник
new
илиmalloc
).Global Arrays
, а не красота и лучше избегать, они не подпадают под ограничения , установленные вstack
, и вам не нужноmalloc
/free
сделать работу с ними.Если рассматривать это с практической, а не теоретической точки зрения, то в 32-битной системе Windows максимальный общий объем памяти, доступный для одного процесса, составляет 2 ГБ. Вы можете преодолеть ограничение, перейдя на 64-разрядную операционную систему с гораздо большей физической памятью, но то, делать это или искать альтернативы, во многом зависит от ваших предполагаемых пользователей и их бюджетов. Вы также можете расширить его, используя PAE .
Тип массива очень важен, так как выравнивание структуры по умолчанию на многих компиляторах составляет 8 байтов, что является очень расточительным, если использование памяти является проблемой. Если вы используете Visual C ++ для работы с Windows, воспользуйтесь директивой #pragma pack как способ преодоления этого.
Еще одна вещь, которую нужно сделать, это посмотреть, что могут помочь вам методы сжатия памяти, такие как разреженные матрицы, сжатие на лету и т. Д. Опять же, это сильно зависит от приложения. Если вы отредактируете свой пост, чтобы дать больше информации о том, что на самом деле находится в ваших массивах, вы можете получить более полезные ответы.
Изменить: Учитывая немного больше информации о ваших точных требованиях, ваши потребности в хранилище, по-видимому, находятся между 7,6 ГБ и 76 ГБ без сжатия, что потребовало бы довольно дорогой 64-битной коробки для хранения в виде массива в памяти в C ++. Возникает вопрос, почему вы хотите хранить данные в памяти, где предполагается скорость доступа, и разрешить произвольный доступ. Лучший способ хранить эти данные вне массива в значительной степени основан на том, как вы хотите получить к ним доступ. Если вам нужен случайный доступ к элементам массива, для большинства приложений существуют способы группировки групп данных, к которым обычно обращаются одновременно. Например, в больших ГИС и пространственных базах данных данные часто разбиваются по географическим областям. В терминах программирования C ++ вы можете переопределить оператор массива [], чтобы при необходимости извлекать части ваших данных из внешнего хранилища.
источник
Я бы согласился с вышесказанным, что если вы начинаете свой массив с
тогда размер ограничен размером целого числа. Но вы всегда можете malloc кусок памяти и иметь указатель на него, настолько большой, насколько вы хотите, если malloc не возвращает NULL.
источник
int oops[INT_MAX]{0};
он генерирует,C2148 - total size of array must not exceed 0x7fffffff bytes
66%
памяти объемом памяти, используемым в настоящее время перед запуском моего приложения для отладки в Windows 10 с VS2017, у меня есть неопределенное ограничение на размер массива int, с которым я могу инициализироваться0
. Иногда я могу сделать это с ~ 257 тысячами элементов, иногда я получаю переполнение стека. Если я добавлю что-то в свое приложение, кроме основного и массива, это число будет уменьшаться (очевидно). Мне пришлось экспериментировать, чтобы определить это число, поэтому я не понимаю, как на эту метрику можно положиться, не зная ваших теоретических пределов в вакууме.Чтобы суммировать ответы, расширить их и ответить на ваш вопрос напрямую:
нет, C ++ не накладывает никаких ограничений на размеры массива.
Но так как массив должен храниться где-то в памяти, применяются ограничения, связанные с памятью, налагаемые другими частями компьютерной системы. Обратите внимание, что эти ограничения напрямую не связаны с размерами (= количество элементов) массива, а скорее с его размером (= количество занятой памяти). Размеры ( D ) и в оперативной памяти размер ( S ) из массива не то же самое, как они связаны памяти , принятым одним элементом ( Е ): S = Д * Е . Е
Сейчас зависит от:
«пустое пространство» (заполнение) между элементами
Также обратите внимание, что вы обычно получаете различные ограничения, связанные с памятью, выделяя данные массива в стеке (как автоматическая переменная
int t[N]
:) или в куче (динамическое размещение сmalloc()
/new
или с использованием механизмов STL), или в статической части памяти процесса (как статическая переменная:)static int t[N]
. Даже при выделении в куче вам все равно нужно небольшое количество памяти в стеке для хранения ссылок на выделенные в куче блоки памяти (но обычно это незначительно).Размер
size_t
типа не влияет на программиста (я предполагаю, что программист используетsize_t
тип для индексации, поскольку он предназначен для него), так как поставщик компилятора долженtypedef
иметь целочисленный тип, достаточно большой, чтобы адресовать максимальный объем памяти, возможный для данной платформы архитектура.Источники ограничений объема памяти проистекают из
Они не могут быть «подправлены» на уровне приложения, но вы можете использовать другой компилятор (для изменения пределов размера стека), либо перенести свое приложение на 64-битную версию, либо перенести его на другую ОС, либо изменить физический / конфигурация виртуальной памяти (виртуальной? физической?) машины.
Нередко (и даже желательно) рассматривать все вышеперечисленные факторы как внешние помехи и, следовательно, как возможные источники ошибок времени выполнения, а также тщательно проверять и реагировать на ошибки, связанные с выделением памяти в программном коде.
Итак, наконец: хотя C ++ не накладывает никаких ограничений, вам все равно придется проверять наличие неблагоприятных условий, связанных с памятью, при запуске вашего кода ... :-)
источник
Как отмечалось много отличных ответов, существует множество ограничений, которые зависят от вашей версии компилятора C ++, операционной системы и характеристик компьютера. Тем не менее, я предлагаю следующий скрипт на Python, который проверяет ограничение на вашем компьютере.
Он использует бинарный поиск и на каждой итерации проверяет, возможен ли средний размер, путем создания кода, который пытается создать массив такого размера. Скрипт пытается скомпилировать его (извините, эта часть работает только в Linux) и настроить бинарный поиск в зависимости от успеха. Проверьте это:
Вы можете сохранить его на своем компьютере и запустить, и он напечатает максимальный размер, который вы можете создать. Для моей машины это 2305843009213693951.
источник
Одна вещь, которую я не думаю, была упомянута в предыдущих ответах.
Я всегда ощущаю «неприятный запах» в смысле рефакторинга, когда люди используют такие вещи в своем дизайне.
Это огромный массив и, возможно, не лучший способ представления ваших данных как с точки зрения эффективности, так и с точки зрения производительности.
веселит,
обкрадывать
источник
Если вам приходится иметь дело с такими большими данными, вам нужно разделить их на управляемые куски. Это не все вписывается в память на любом маленьком компьютере. Вероятно, вы можете загрузить часть данных с диска (независимо от того, что уместно), выполнить ваши вычисления и внести в них изменения, сохранить их на диск, а затем повторить до завершения.
источник
Как ни досадно неспецифично, как все текущие ответы, они в основном правильные, но со многими оговорками, не всегда упоминаемыми. Суть в том, что у вас есть два верхних предела, и только один из них действительно определен, так что YMMV :
1. Ограничение времени компиляции
В основном то, что позволит ваш компилятор. Для Visual C ++ 2017 в 64-разрядной версии Windows 10 это мой максимальный лимит во время компиляции до ограничения в 2 ГБ,
Если бы я сделал это вместо этого,
Я бы получил:
Я не уверен, как 2G коррелирует с
255999996
/7
. Я погуглил оба числа, и единственное, что я смог найти, возможно, было связано с этим * nix Q & A о проблеме точности сdc
. В любом случае, кажется, что не имеет значения, какой тип массива int вы пытаетесь заполнить, сколько элементов может быть выделено.2. Ограничения времени выполнения
Ваш стек и куча имеют свои ограничения. Эти ограничения являются значениями, которые изменяются в зависимости от доступных системных ресурсов, а также от того, насколько «тяжелым» является само ваше приложение. Например, с моими текущими системными ресурсами я могу заставить это работать:
Но если я немного подправлю ...
Бам! Переполнение стека!
И просто, чтобы детализировать всю тяжесть вашего приложения, это было хорошо, чтобы пойти:
Но это вызвало переполнение стека:
источник
Я удивлен, что функция-член max_size () в std :: vector здесь не упоминалась.
Мы знаем, что
std::vector
он реализован в виде динамического массива под капотом, поэтомуmax_size()
должен дать очень точное приближение к максимальной длине динамического массива на вашей машине.Следующая программа создает таблицу приблизительной максимальной длины массива для различных типов данных.
На моем macOS (clang версии 5.0.1) я получаю следующее:
На ideone gcc 8.3 я получаю:
Следует отметить, что это теоретический предел, и на большинстве компьютеров вам не хватит памяти задолго до того, как вы достигнете этого предела. Например, мы видим, что для типа
char
ongcc
максимальное количество элементов равно maxstd::size_t
. Пытаясь это , мы получаем ошибку:Наконец, как указывает @MartinYork, для статических массивов максимальный размер ограничен размером вашего стека.
источник
Как уже указывалось, размер массива ограничен вашим оборудованием и вашей ОС (man ulimit). Однако ваше программное обеспечение может быть ограничено только вашим творческим потенциалом. Например, можете ли вы сохранить свой «массив» на диске? Вам действительно нужны длинные длинные целые? Вам действительно нужен плотный массив? Вам вообще нужен массив?
Одним из простых решений было бы использовать 64-битный Linux. Даже если у вас недостаточно физического ОЗУ для массива, ОС позволит вам распределить память, как если бы вы это делали, поскольку виртуальная память, доступная вашему процессу, вероятно, намного больше, чем физическая память. Если вам действительно нужен доступ ко всему в массиве, это равносильно хранению его на диске. В зависимости от ваших шаблонов доступа, могут быть более эффективные способы сделать это (например, используя mmap () или просто последовательно хранить данные в файле (в этом случае 32-битного Linux будет достаточно)).
источник
я бы обойти это, создав 2d динамический массив:
Подробнее об этом здесь https://stackoverflow.com/a/936702/3517001
источник