Hay dos límites, ambos no impuestos por C ++ sino por el hardware.
El primer límite (nunca se debe alcanzar) está establecido por las restricciones del tipo de tamaño utilizado para describir un índice en la matriz (y el tamaño del mismo). Está dado por el valor máximo que el sistemastd::size_t
puede tomar . Este tipo de datos es lo suficientemente grande como para contener el tamaño en bytes de cualquier objeto
El otro límite es un límite de memoria física. Cuanto más grandes sean sus objetos en la matriz, antes se alcanzará este límite porque la memoria está llena. Por ejemplo, a vector<int>
de un tamaño dado n generalmente toma varias veces más memoria que una matriz de tipo vector<char>
(menos un valor constante pequeño), ya int
que generalmente es mayor que char
. Por lo tanto, a vector<char>
puede contener más elementos que vector<int>
antes de que la memoria esté llena. Lo mismo cuenta para matrices de estilo C sin formato como int[]
y char[]
.
Además, este límite superior puede estar influenciado por el tipo de allocator
utilizado para construir el vector
porque unallocator
es libre de administrar la memoria de la forma que desee. Un asignador muy extraño pero concebible podría agrupar la memoria de tal manera que instancias idénticas de un objeto compartan recursos. De esta manera, podría insertar una gran cantidad de objetos idénticos en un contenedor que de otro modo usaría toda la memoria disponible.
Aparte de eso, C ++ no impone ningún límite.
new
omalloc
. Se puede acceder a un trozo de memoria más grande que una matriz a través del puntero.Nadie mencionó el límite en el tamaño del marco de la pila .
Hay dos lugares donde se puede asignar memoria:
El límite de tamaño aquí es una combinación de hardware disponible y la capacidad del sistema operativo para simular el espacio mediante el uso de otros dispositivos para almacenar temporalmente datos no utilizados ( es decir, mover páginas al disco duro).
El límite de tamaño aquí está definido por el compilador (con posibles límites de hardware). Si lee la documentación del compilador, a menudo puede modificar este tamaño.
Por lo tanto, si asigna una matriz dinámicamente (el límite es grande y otras publicaciones lo describen en detalle).
Alternativamente, si la matriz está asignada en la pila, entonces está limitado por el tamaño del marco de la pila. Los vectores NB y otros contenedores tienen una pequeña presencia en la pila, pero generalmente la mayor parte de los datos estará en el montón.
fuente
new
omalloc
).Global Arrays
aunque no es una belleza y es mejor evitarlo, estos no están sujetos a las restricciones de lastack
, y no necesitamalloc
/free
trabaja con ellos.Mirándolo desde un punto de vista práctico más que teórico, en un sistema Windows de 32 bits, la cantidad total máxima de memoria disponible para un solo proceso es de 2 GB. Puede romper el límite yendo a un sistema operativo de 64 bits con mucha más memoria física, pero si hacer esto o buscar alternativas depende en gran medida de los usuarios previstos y sus presupuestos. También puede extenderlo un poco usando PAE .
El tipo de matriz es muy importante, ya que la alineación predeterminada de la estructura en muchos compiladores es de 8 bytes, lo cual es un desperdicio si el uso de memoria es un problema. Si está utilizando Visual C ++ para apuntar a Windows, consulte la directiva #pragma pack como una forma de superar esto.
Otra cosa que debe hacer es ver qué pueden ayudarle las técnicas de compresión de memoria, como matrices dispersas, compresión sobre la marcha, etc. De nuevo, esto depende en gran medida de la aplicación. Si edita su publicación para dar más información sobre lo que realmente está en sus matrices, puede obtener respuestas más útiles.
Editar: Dada un poco más de información sobre sus requisitos exactos, sus necesidades de almacenamiento parecen estar entre 7.6 GB y 76 GB sin comprimir, lo que requeriría una caja de 64 bits bastante costosa para almacenar como una matriz en memoria en C ++. Plantea la pregunta de por qué desea almacenar los datos en la memoria, donde se presume la velocidad de acceso, y permitir el acceso aleatorio. La mejor manera de almacenar estos datos fuera de una matriz se basa básicamente en cómo desea acceder a ellos. Si necesita acceder a los miembros de la matriz al azar, para la mayoría de las aplicaciones, existen formas de agrupar grupos de datos a los que se accede al mismo tiempo. Por ejemplo, en grandes SIG y bases de datos espaciales, los datos a menudo se agrupan por área geográfica. En los términos de programación de C ++, puede anular el operador de matriz [] para obtener partes de sus datos del almacenamiento externo según sea necesario.
fuente
Estoy de acuerdo con lo anterior, que si está inicializando su matriz con
entonces SIZE está limitado por el tamaño de un número entero. Pero siempre puedes malloc un trozo de memoria y tener un puntero a él, tan grande como quieras siempre que malloc no devuelva NULL.
fuente
int oops[INT_MAX]{0};
Genera,C2148 - total size of array must not exceed 0x7fffffff bytes
66%
memoria utilizada actualmente antes de iniciar mi aplicación como depuración en Windows 10 con VS2017, tengo un límite indefinido sobre qué tan grande de una matriz interna puedo inicializar0
. A veces puedo hacerlo con ~ 257k elementos, a veces obtengo un desbordamiento de pila. Si agrego algo a mi aplicación además del principal y la matriz, ese número disminuye (obviamente). Tuve que experimentar para determinar este número, por lo que no veo cómo se puede confiar en esta métrica más allá de conocer sus límites teóricos en el vacío.Para resumir las respuestas, extiéndalas y responda su pregunta directamente:
No, C ++ no impone ningún límite para las dimensiones de una matriz.
Pero como la matriz debe almacenarse en algún lugar de la memoria, también se aplican los límites relacionados con la memoria impuestos por otras partes del sistema informático. Tenga en cuenta que estos límites no se relacionan directamente con las dimensiones (= número de elementos) de la matriz, sino con su tamaño (= cantidad de memoria tomada). Dimensiones ( D ) y el tamaño en memoria ( S ) de una matriz no es el mismo, ya que están relacionadas por la memoria tomada por un solo elemento ( E ): S = D * E .
AhoraE depende de:
'espacio desperdiciado' (relleno) entre elementos
También tenga en cuenta que generalmente obtiene diferentes limitaciones relacionadas con la memoria al asignar los datos de la matriz en la pila (como una variable automática
int t[N]
:), o en el montón (ubicación dinámica conmalloc()
/new
o utilizando mecanismos STL), o en la parte estática de la memoria del proceso (como Una variable estática:)static int t[N]
. Incluso al asignar en el montón, aún necesita una pequeña cantidad de memoria en la pila para almacenar referencias a los bloques de memoria asignados al montón (pero esto es insignificante, por lo general).El tamaño del
size_t
tipo no tiene influencia en el programador (supongo que el programador usa elsize_t
tipo para indexar, ya que está diseñado para ello), ya que el proveedor del compilador lo tienetypedef
en un tipo entero lo suficientemente grande como para abordar la cantidad máxima de memoria posible para la plataforma dada arquitectura.Las fuentes de las limitaciones del tamaño de la memoria provienen de
No se pueden 'ajustar' a nivel de aplicación, pero puede usar un compilador diferente (para cambiar los límites de tamaño de pila), o portar su aplicación a 64 bits, o portarla a otro sistema operativo, o cambiar el físico / configuración de memoria virtual de la máquina (¿virtual? ¿física?).
No es raro (e incluso aconsejable) tratar todos los factores anteriores como perturbaciones externas y, por lo tanto, como posibles fuentes de errores de tiempo de ejecución, y verificar cuidadosamente y reaccionar a los errores relacionados con la asignación de memoria en el código de su programa.
Entonces, finalmente: aunque C ++ no impone ningún límite, aún debe verificar las condiciones adversas relacionadas con la memoria al ejecutar su código ... :-)
fuente
Como se observaron muchas respuestas excelentes, hay muchos límites que dependen de su versión del compilador de C ++, el sistema operativo y las características de la computadora. Sin embargo, sugiero el siguiente script en Python que verifica el límite en su máquina.
Utiliza la búsqueda binaria y en cada iteración comprueba si el tamaño medio es posible creando un código que intente crear una matriz del tamaño. El script intenta compilarlo (lo siento, esta parte solo funciona en Linux) y ajustar la búsqueda binaria según el éxito. Echale un vistazo:
Puede guardarlo en su máquina e iniciarlo, e imprimirá el tamaño máximo que puede crear. Para mi máquina es 2305843009213693951.
fuente
Una cosa que no creo que se haya mencionado en las respuestas anteriores.
Siempre estoy sintiendo un "mal olor" en el sentido de refactorización cuando la gente usa tales cosas en su diseño.
Esa es una gran variedad y posiblemente no sea la mejor manera de representar sus datos tanto desde el punto de vista de la eficiencia como desde el punto de vista del rendimiento.
salud,
Robar
fuente
Si tiene que lidiar con datos tan grandes, deberá dividirlos en fragmentos manejables. No cabe en la memoria de ninguna computadora pequeña. Probablemente pueda cargar una parte de los datos del disco (lo que sea razonablemente adecuado), realizar sus cálculos y cambios, almacenarlos en el disco y luego repetir hasta completar.
fuente
Tan molestamente inespecífico como lo son todas las respuestas actuales, en su mayoría son correctas pero con muchas advertencias, no siempre mencionadas. La esencia es que tienes dos límites superiores, y solo uno de ellos es algo realmente definido, por lo que YMMV :
1. Límites de tiempo de compilación
Básicamente, lo que permitirá su compilador. Para Visual C ++ 2017 en un cuadro de Windows 10 x64, este es mi límite máximo en tiempo de compilación antes de incurrir en el límite de 2 GB,
Si hice esto en su lugar,
Obtendría:
No estoy seguro de cómo 2G correllates a
255999996
/7
. Busqué en Google ambos números, y lo único que pude encontrar que posiblemente estaba relacionado fue este * nix Q&A sobre un problema de precisióndc
. De cualquier manera, no parece importar qué tipo de matriz int está tratando de llenar, sino cuántos elementos se pueden asignar.2. Límites de tiempo de ejecución
Su pila y montón tienen sus propias limitaciones. Estos límites son valores que cambian según los recursos del sistema disponibles, así como cuán "pesada" es su aplicación. Por ejemplo, con mis recursos actuales del sistema, puedo hacer que esto se ejecute:
Pero si lo retoco un poco ...
Bam! ¡Desbordamiento de pila!
Y solo para detallar todo el peso de su punto de aplicación, esto fue bueno:
Pero esto causó un desbordamiento de pila:
fuente
Me sorprende que la función miembro max_size () de std :: vector no se haya mencionado aquí.
Sabemos que
std::vector
se implementa como una matriz dinámica debajo del capó, por lo quemax_size()
debe proporcionar una aproximación muy cercana de la longitud máxima de una matriz dinámica en su máquina.El siguiente programa crea una tabla de longitud de matriz máxima aproximada para varios tipos de datos.
En mi macOS (clang versión 5.0.1), obtengo lo siguiente:
En ideone gcc 8.3 obtengo:
Cabe señalar que este es un límite teórico y que en la mayoría de las computadoras, se quedará sin memoria mucho antes de alcanzar este límite. Por ejemplo, vemos que para type
char
ongcc
, el número máximo de elementos es igual al máximo destd::size_t
. Al intentar esto , obtenemos el error:Por último, como señala @MartinYork, para las matrices estáticas el tamaño máximo está limitado por el tamaño de su pila.
fuente
Como ya se ha señalado, el tamaño de la matriz está limitado por su hardware y su sistema operativo (man ulimit). Sin embargo, su software solo puede estar limitado por su creatividad. Por ejemplo, ¿puede almacenar su "matriz" en el disco? ¿Realmente necesitas entradas largas y largas? ¿Realmente necesitas una matriz densa? ¿Necesitas una matriz?
Una solución simple sería usar Linux de 64 bits. Incluso si físicamente no tiene suficiente memoria RAM para su matriz, el sistema operativo le permitirá asignar memoria como lo hace, ya que la memoria virtual disponible para su proceso es probablemente mucho más grande que la memoria física. Si realmente necesita acceder a todo en la matriz, esto equivale a almacenarlo en el disco. Dependiendo de sus patrones de acceso, puede haber formas más eficientes de hacerlo (es decir: usando mmap (), o simplemente almacenando los datos secuencialmente en un archivo (en cuyo caso, Linux de 32 bits sería suficiente)).
fuente
Yo evitaría esto haciendo una matriz dinámica 2D:
más sobre esto aquí https://stackoverflow.com/a/936702/3517001
fuente