C ++ heredó matrices de C donde se usan prácticamente en todas partes. C ++ proporciona abstracciones que son más fáciles de usar y menos propensas a errores ( std::vector<T>
desde C ++ 98 y std::array<T, n>
desde C ++ 11 ), por lo que la necesidad de matrices no surge con tanta frecuencia como en C. Sin embargo, cuando lee el legado código o interactuar con una biblioteca escrita en C, debe tener una idea clara de cómo funcionan las matrices.
Estas preguntas frecuentes se dividen en cinco partes:
- matrices en el nivel de tipo y elementos de acceso
- creación e inicialización de matrices
- asignación y paso de parámetros
- matrices multidimensionales y matrices de punteros
- trampas comunes al usar matrices
Si cree que falta algo importante en estas preguntas frecuentes, escriba una respuesta y enlácela aquí como parte adicional.
En el siguiente texto, "matriz" significa "matriz C", no la plantilla de clase std::array
. Se asume el conocimiento básico de la sintaxis del declarante C. Tenga en cuenta que el uso manual de new
y delete
como se demuestra a continuación es extremadamente peligroso ante las excepciones, pero ese es el tema de otras preguntas frecuentes .
(Nota: Esto está destinado a ser una entrada a las preguntas frecuentes de C ++ de Stack Overflow . Si desea criticar la idea de proporcionar preguntas frecuentes en este formulario, entonces la publicación en meta que comenzó todo esto sería el lugar para hacerlo. Respuestas a esa pregunta se monitorea en la sala de chat de C ++ , donde la idea de las preguntas frecuentes comenzó en primer lugar, por lo que es muy probable que su respuesta sea leída por aquellos a quienes se les ocurrió la idea).
std::array
s,std::vector
sygsl::span
s, francamente esperaría una pregunta frecuente sobre cómo usar matrices en C ++ para decir "Por ahora, puede comenzar a considerar simplemente, bueno, no usarlos".Respuestas:
Matrices en el nivel de tipo
Un tipo de matriz se denota como
T[n]
dondeT
está el tipo de elemento yn
es un tamaño positivo , el número de elementos en la matriz. El tipo de matriz es un tipo de producto del tipo de elemento y el tamaño. Si uno o ambos ingredientes difieren, obtienes un tipo distinto:Tenga en cuenta que el tamaño es parte del tipo, es decir, los tipos de matriz de diferente tamaño son tipos incompatibles que no tienen absolutamente nada que ver entre sí.
sizeof(T[n])
es equivalente an * sizeof(T)
.Decaimiento de matriz a puntero
El único "conexión" entre
T[n]
yT[m]
es que ambos tipos implícitamente pueden ser convertidos aT*
, y el resultado de esta conversión es un puntero al primer elemento de la matriz. Es decir, en cualquier lugar dondeT*
se requiera un, puede proporcionar unT[n]
, y el compilador proporcionará silenciosamente ese puntero:Esta conversión se conoce como "decaimiento de matriz a puntero", y es una fuente importante de confusión. El tamaño de la matriz se pierde en este proceso, ya que ya no es parte del tipo (
T*
). Pro: olvidar el tamaño de una matriz en el nivel de tipo permite que un puntero apunte al primer elemento de una matriz de cualquier tamaño. Con: dado un puntero al primer elemento (o cualquier otro) de una matriz, no hay forma de detectar qué tan grande es esa matriz o dónde apunta exactamente el puntero en relación con los límites de la matriz. Los punteros son extremadamente estúpidos .Las matrices no son punteros
El compilador generará silenciosamente un puntero al primer elemento de una matriz siempre que se considere útil, es decir, cuando una operación falle en una matriz pero tenga éxito en un puntero. Esta conversión de matriz a puntero es trivial, ya que el valor del puntero resultante es simplemente la dirección de la matriz. Tenga en cuenta que el puntero no se almacena como parte de la matriz en sí (o en cualquier otro lugar de la memoria). Una matriz no es un puntero.
Un contexto importante en el que una matriz no se desintegra en un puntero a su primer elemento es cuando
&
se le aplica el operador. En ese caso, el&
operador arroja un puntero a toda la matriz, no solo un puntero a su primer elemento. Aunque en ese caso los valores (las direcciones) son los mismos, un puntero al primer elemento de una matriz y un puntero a toda la matriz son tipos completamente distintos:El siguiente arte ASCII explica esta distinción:
Observe cómo el puntero al primer elemento solo apunta a un único entero (representado como un cuadro pequeño), mientras que el puntero a toda la matriz apunta a una matriz de 8 enteros (representado como un cuadro grande).
La misma situación surge en las clases y es quizás más obvia. Un puntero a un objeto y un puntero a su primer miembro de datos tienen el mismo valor (la misma dirección), pero son tipos completamente distintos.
Si no está familiarizado con la sintaxis del declarador C, los paréntesis en el tipo
int(*)[8]
son esenciales:int(*)[8]
es un puntero a una matriz de 8 enteros.int*[8]
es una matriz de 8 punteros, cada elemento de tipoint*
.Acceso a elementos
C ++ proporciona dos variaciones sintácticas para acceder a elementos individuales de una matriz. Ninguno de los dos es superior al otro, y debes familiarizarte con ambos.
Aritmética de puntero
Dado un puntero
p
al primer elemento de una matriz, la expresiónp+i
produce un puntero al elemento i-ésimo de la matriz. Al hacer referencia a ese puntero posteriormente, se puede acceder a elementos individuales:Si
x
denota una matriz , entonces la descomposición de matriz a puntero se activará, porque agregar una matriz y un entero no tiene sentido (no hay una operación más en las matrices), pero tiene sentido agregar un puntero y un entero:(Tenga en cuenta que el puntero generado implícitamente no tiene nombre, así que escribí
x+0
para identificarlo).Si, por otro lado,
x
denota un puntero al primer elemento (o cualquier otro) de una matriz, entonces la descomposición de matriz a puntero no es necesaria, porque el puntero en el quei
se va a agregar ya existe:Tenga en cuenta que en el caso representado,
x
es una variable de puntero (discernible por el pequeño cuadro al ladox
), pero podría ser el resultado de una función que devuelve un puntero (o cualquier otra expresión de tipoT*
).Operador de indexación
Como la sintaxis
*(x+i)
es un poco torpe, C ++ proporciona la sintaxis alternativax[i]
:Debido al hecho de que la suma es conmutativa, el siguiente código hace exactamente lo mismo:
La definición del operador de indexación conduce a la siguiente equivalencia interesante:
Sin embargo,
&x[0]
generalmente no es equivalente ax
. El primero es un puntero, el último una matriz. Sólo cuando la caries los factores desencadenantes de contexto array-a-puntero puedex
y&x[0]
ser utilizado de manera intercambiable. Por ejemplo:En la primera línea, el compilador detecta una asignación de un puntero a un puntero, que tiene éxito trivialmente. En la segunda línea, detecta una asignación de una matriz a un puntero. Como esto no tiene sentido (pero la asignación de puntero a puntero tiene sentido), la descomposición de matriz a puntero se activa como de costumbre.
Rangos
Una matriz de tipos
T[n]
tienen
elementos, indexados de0
an-1
; No hay elementon
. Y, sin embargo, para admitir rangos medio abiertos (donde el comienzo es inclusivo y el final es exclusivo ), C ++ permite el cálculo de un puntero al elemento n-ésimo (inexistente), pero es ilegal desreferenciar ese puntero:Por ejemplo, si desea ordenar una matriz, los dos siguientes funcionarían igual de bien:
Tenga en cuenta que es ilegal proporcionar
&x[n]
como segundo argumento, ya que esto es equivalente a&*(x+n)
, y la sub-expresión*(x+n)
técnicamente invoca un comportamiento indefinido en C ++ (pero no en C99).También tenga en cuenta que simplemente podría proporcionar
x
como primer argumento. Eso es un poco demasiado breve para mi gusto, y también hace que la deducción de argumentos de plantilla sea un poco más difícil para el compilador, porque en ese caso el primer argumento es una matriz pero el segundo argumento es un puntero. (Nuevamente, la descomposición de matriz a puntero se activa).fuente
Los programadores a menudo confunden matrices multidimensionales con matrices de punteros.
Matrices multidimensionales
La mayoría de los programadores están familiarizados con las matrices multidimensionales con nombre, pero muchos desconocen el hecho de que la matriz multidimensional también se puede crear de forma anónima. Las matrices multidimensionales a menudo se denominan "matrices de matrices" o " matrices multidimensionales verdaderas ".
Matrices multidimensionales con nombre
Cuando se utilizan matrices multidimensionales con nombre, todas las dimensiones deben conocerse en tiempo de compilación:
Así es como se ve una matriz multidimensional con nombre en la memoria:
Tenga en cuenta que las cuadrículas 2D como las anteriores son meramente visualizaciones útiles. Desde el punto de vista de C ++, la memoria es una secuencia "plana" de bytes. Los elementos de una matriz multidimensional se almacenan en orden de fila mayor. Es decir,
connect_four[0][6]
yconnect_four[1][0]
son vecinos en la memoria. De hecho,connect_four[0][7]
yconnect_four[1][0]
denota el mismo elemento! Esto significa que puede tomar matrices multidimensionales y tratarlas como matrices unidimensionales grandes:Matrices multidimensionales anónimas
Con matrices multidimensionales anónimas, todas las dimensiones, excepto la primera, deben conocerse en tiempo de compilación:
Así es como se ve una matriz multidimensional anónima en la memoria:
Tenga en cuenta que la matriz misma todavía está asignada como un bloque único en la memoria.
Matrices de punteros
Puede superar la restricción de ancho fijo introduciendo otro nivel de indirección.
Conjuntos de punteros nombrados
Aquí hay una matriz con nombre de cinco punteros que se inicializan con matrices anónimas de diferentes longitudes:
Y así es como se ve en la memoria:
Como cada línea se asigna individualmente ahora, ver matrices 2D como matrices 1D ya no funciona.
Matrices anónimas de punteros
Aquí hay una matriz anónima de 5 (o cualquier otro número de) punteros que se inicializan con matrices anónimas de diferentes longitudes:
Y así es como se ve en la memoria:
Conversiones
La descomposición de matriz a puntero se extiende naturalmente a matrices de matrices y matrices de punteros:
Sin embargo, no hay conversión implícita de
T[h][w]
aT**
. Si existiera tal conversión implícita, el resultado sería un puntero al primer elemento de una matriz deh
punteros aT
(cada uno apuntando al primer elemento de una línea en la matriz 2D original), pero esa matriz de puntero no existe en ninguna parte memoria todavía. Si desea dicha conversión, debe crear y completar la matriz de punteros requerida manualmente:Tenga en cuenta que esto genera una vista de la matriz multidimensional original. Si necesita una copia, debe crear matrices adicionales y copiar los datos usted mismo:
fuente
int connect_four[H][7];
,int connect_four[6][W];
int connect_four[H][W];
así comoint (*p)[W] = new int[6][W];
yint (*p)[W] = new int[H][W];
son declaraciones válidas, cuándoH
yW
se conocen en tiempo de compilación.Asignación
Sin ninguna razón en particular, las matrices no pueden asignarse entre sí. Use en su
std::copy
lugar:Esto es más flexible de lo que podría proporcionar la verdadera asignación de matriz porque es posible copiar segmentos de matrices más grandes en matrices más pequeñas.
std::copy
generalmente está especializado para tipos primitivos para dar el máximo rendimiento. Es poco probable questd::memcpy
funcione mejor. En caso de duda, mida.Aunque no puede asignar matrices directamente, puede asignar estructuras y clases que contienen miembros de la matriz. Esto se debe a que los miembros de la matriz son copiados por el operador de asignación, que el compilador proporciona como predeterminado. Si define el operador de asignación manualmente para sus propios tipos de estructura o clase, debe recurrir a la copia manual para los miembros de la matriz.
Paso de parámetros
Las matrices no se pueden pasar por valor. Puede pasarlos por puntero o por referencia.
Pase por puntero
Dado que las matrices en sí mismas no se pueden pasar por valor, generalmente se pasa un puntero a su primer elemento por valor. Esto a menudo se llama "pasar por puntero". Dado que el tamaño de la matriz no se puede recuperar a través de ese puntero, debe pasar un segundo parámetro que indica el tamaño de la matriz (la solución clásica de C) o un segundo puntero que apunta después del último elemento de la matriz (la solución iteradora de C ++) :
Como alternativa sintáctica, también puede declarar parámetros como
T p[]
, y significa exactamente lo mismo queT* p
en el contexto de las listas de parámetros solamente :Se puede pensar en el compilador como la reescritura
T p[]
deT *p
en el contexto de las listas de parámetros únicos . Esta regla especial es en parte responsable de toda la confusión sobre las matrices y los punteros. En cualquier otro contexto, declarar algo como una matriz o como un puntero hace una gran diferencia.Desafortunadamente, también puede proporcionar un tamaño en un parámetro de matriz que el compilador ignora silenciosamente. Es decir, las siguientes tres firmas son exactamente equivalentes, como lo indican los errores del compilador:
Pase por referencia
Las matrices también se pueden pasar por referencia:
En este caso, el tamaño de la matriz es significativo. Dado que escribir una función que solo acepta matrices de exactamente 8 elementos es de poca utilidad, los programadores generalmente escriben funciones como plantillas:
Tenga en cuenta que solo puede llamar a dicha plantilla de función con una matriz real de enteros, no con un puntero a un entero. El tamaño de la matriz se infiere automáticamente y, para cada tamaño
n
, se crea una instancia de una función diferente de la plantilla. También puede escribir plantillas de funciones bastante útiles que se resumen tanto del tipo de elemento como del tamaño.fuente
void foo(int a[3])
a
parezca que uno está pasando la matriz por valor, la modificacióna
internafoo
modificará la matriz original. Esto debería estar claro porque las matrices no se pueden copiar, pero puede valer la pena reforzar eso.ranges::copy(a, b)
int sum( int size_, int a[size_]);
- desde (creo) C99 en adelante5. Errores comunes al usar matrices.
5.1 Peligro: Confiando en el tipo de enlace inseguro.
Bien, le han dicho, o se ha enterado usted mismo, que los globales (variables de alcance del espacio de nombres a las que se puede acceder fuera de la unidad de traducción) son Evil ™. ¿Pero sabías cuán verdaderamente malvados son? Considere el siguiente programa, que consta de dos archivos [main.cpp] y [numbers.cpp]:
En Windows 7 esto compila y enlaza bien tanto con MinGW g ++ 4.4.1 como con Visual C ++ 10.0.
Como los tipos no coinciden, el programa se bloquea cuando lo ejecuta.
Explicación formal: el programa tiene Comportamiento Indefinido (UB), y en lugar de fallar, por lo tanto, simplemente puede colgar, o tal vez no hacer nada, o puede enviar correos electrónicos amenazantes a los presidentes de los EE. UU., Rusia, India, China y Suiza, y haz que los Demonios Nasales salgan volando de tu nariz.
Explicación en
main.cpp
la práctica: en la matriz se trata como un puntero, ubicado en la misma dirección que la matriz. Para el ejecutable de 32 bits, esto significa que el primerint
valor de la matriz se trata como un puntero. Es decir, enmain.cpp
lanumbers
variable contiene, o parece contener,(int*)1
. Esto hace que el programa acceda a la memoria en la parte inferior del espacio de direcciones, que está convencionalmente reservado y causa trampa. Resultado: tienes un accidente.Los compiladores tienen pleno derecho a no diagnosticar este error, porque C ++ 11 §3.5 / 10 dice, sobre el requisito de tipos compatibles para las declaraciones,
El mismo párrafo detalla la variación permitida:
Esta variación permitida no incluye declarar un nombre como una matriz en una unidad de traducción y como un puntero en otra unidad de traducción.
5.2 Peligro: Hacer optimización prematura (
memset
y amigos).Aún no escrito
5.3 Dificultad: usar el lenguaje C para obtener el número de elementos.
Con experiencia profunda en C es natural escribir ...
Como un
array
decaimiento del puntero al primer elemento donde sea necesario, la expresiónsizeof(a)/sizeof(a[0])
también se puede escribir comosizeof(a)/sizeof(*a)
. Significa lo mismo, y no importa cómo esté escrito, es el idioma C para encontrar los elementos numéricos de la matriz.Principal escollo: el idioma C no es seguro. Por ejemplo, el código ...
pasa un puntero a
N_ITEMS
y, por lo tanto, lo más probable es que produzca un resultado incorrecto. Compilado como un ejecutable de 32 bits en Windows 7 produce ...int const a[7]
a justint const a[]
.int const a[]
aint const* a
.N_ITEMS
Por lo tanto, se invoca con un puntero.sizeof(array)
(tamaño de un puntero) es entonces 4.sizeof(*array)
es equivalente asizeof(int)
, que para un ejecutable de 32 bits también es 4.Para detectar este error en tiempo de ejecución, puede hacer ...
La detección de errores en tiempo de ejecución es mejor que la ausencia de detección, pero desperdicia un poco de tiempo de procesador y quizás mucho más tiempo de programador. ¡Mejor con detección en tiempo de compilación! Y si está contento de no admitir matrices de tipos locales con C ++ 98, puede hacerlo:
Compilando esta definición sustituida en el primer programa completo, con g ++, obtuve ...
Cómo funciona: la matriz se pasa por referencia a
n_items
, y por lo tanto no decae al puntero al primer elemento, y la función solo puede devolver el número de elementos especificados por el tipo.Con C ++ 11 puede usar esto también para matrices de tipo local, y es el idioma seguro de C ++ para encontrar el número de elementos de una matriz.
5.4 Peligro de C ++ 11 y C ++ 14: uso de una
constexpr
función de tamaño de matrizCon C ++ 11 y versiones posteriores es natural, ¡pero como verás peligroso !, reemplazar la función C ++ 03
con
donde el cambio significativo es el uso de
constexpr
, que permite que esta función produzca una constante de tiempo de compilación .Por ejemplo, en contraste con la función C ++ 03, dicha constante de tiempo de compilación se puede usar para declarar una matriz del mismo tamaño que otra:
Pero considere este código usando la
constexpr
versión:La trampa: a partir de julio de 2015, lo anterior se compila con MinGW-64 5.1.0 con
C ++ 11 ++ 14 C $ 5.19 / 2 nueve º tablero-pedantic-errors
, y, probando con los compiladores en línea en gcc.godbolt.org/ , también con clang 3.0 y clang 3.2, pero no con clang 3.3, 3.4. 1, 3.5.0, 3.5.1, 3.6 (rc1) o 3.7 (experimental). E importante para la plataforma Windows, no se compila con Visual C ++ 2015. La razón es una declaración C ++ 11 / C ++ 14 sobre el uso de referencias enconstexpr
expresiones:Uno siempre puede escribir más detallado
... pero esto falla cuando
Collection
no es una matriz en bruto.Para manejar colecciones que pueden ser no matrices, se necesita la capacidad de sobrecarga de una
n_items
función, pero también, para el tiempo de compilación, se necesita una representación en tiempo de compilación del tamaño de la matriz. Y la solución clásica de C ++ 03, que funciona bien también en C ++ 11 y C ++ 14, es dejar que la función informe su resultado no como un valor sino a través de su tipo de resultado de función . Por ejemplo así:Acerca de la elección del tipo de retorno para
static_n_items
: este código no se usastd::integral_constant
porque constd::integral_constant
el resultado se representa directamente como unconstexpr
valor, reintroduciendo el problema original. En lugar de unaSize_carrier
clase, se puede dejar que la función devuelva directamente una referencia a una matriz. Sin embargo, no todos están familiarizados con esa sintaxis.Acerca de la nomenclatura: parte de esta solución al problema
constexpr
-invalido-debido a una referencia es hacer explícita la elección del tiempo de compilación constante.Afortunadamente, oops-there-was-a-reference-implicate-in-your-
constexpr
issue se solucionará con C ++ 17, pero hasta entonces una macro como laSTATIC_N_ITEMS
anterior proporciona portabilidad, por ejemplo, a los compiladores clang y Visual C ++, conservando el tipo la seguridad.Relacionado: las macros no respetan los ámbitos, por lo que para evitar colisiones de nombres puede ser una buena idea usar un prefijo de nombre, por ejemplo
MYLIB_STATIC_N_ITEMS
.fuente
Segmentation fault
... ¡Finalmente encontré / entendí después de leer sus explicaciones! Por favor escriba su sección §5.2 :-) Saludossize_t
eso, eso no tiene ventajas que conozco para las plataformas modernas, pero tiene varios problemas debido a las reglas de conversión de tipo implícito de C y C ++. Es decir,ptrdiff_t
se usa de manera muy intencional, para evitar los problemas consize_t
. Sin embargo, se debe tener en cuenta que g ++ tiene un problema al hacer coincidir el tamaño de la matriz con el parámetro de la plantilla a menos que seasize_t
(no creo que este problema específico del compilador con nosize_t
sea importante, pero YMMV).size_t
para denotar tamaños de matrices, no, por supuesto, no lo hace.Creación e inicialización de matrices
Al igual que con cualquier otro tipo de objeto C ++, las matrices se pueden almacenar directamente en variables con nombre (entonces el tamaño debe ser una constante de tiempo de compilación; C ++ no admite VLA ), o se pueden almacenar de forma anónima en el montón y acceder indirectamente a través de punteros (solo entonces se puede calcular el tamaño en tiempo de ejecución).
Matrices automáticas
Las matrices automáticas (matrices que viven "en la pila") se crean cada vez que el flujo de control pasa a través de la definición de una variable de matriz local no estática:
La inicialización se realiza en orden ascendente. Tenga en cuenta que los valores iniciales dependen del tipo de elemento
T
:T
es un POD (comoint
en el ejemplo anterior), no se lleva a cabo la inicialización.T
inicializa todos los elementos.T
no proporciona un constructor predeterminado accesible, el programa no se compila.Alternativamente, los valores iniciales se pueden especificar explícitamente en el inicializador de matriz , una lista separada por comas rodeada de llaves:
Como en este caso el número de elementos en el inicializador de matriz es igual al tamaño de la matriz, especificar el tamaño manualmente es redundante. El compilador puede deducirlo automáticamente:
También es posible especificar el tamaño y proporcionar un inicializador de matriz más corto:
En ese caso, los elementos restantes están inicializados en cero . Tenga en cuenta que C ++ permite un inicializador de matriz vacío (todos los elementos están inicializados en cero), mientras que C89 no (se requiere al menos un valor). También tenga en cuenta que los inicializadores de matriz solo se pueden usar para inicializar matrices; luego no se pueden usar en tareas.
Matrices estáticas
Las matrices estáticas (matrices que viven "en el segmento de datos") son variables de matriz local definidas con la
static
palabra clave y las variables de matriz en el ámbito del espacio de nombres ("variables globales"):(Tenga en cuenta que las variables en el ámbito del espacio de nombres son implícitamente estáticas. Agregar la
static
palabra clave a su definición tiene un significado completamente diferente y obsoleto ).Así es como las matrices estáticas se comportan de manera diferente a las automáticas:
(Ninguno de los anteriores es específico para las matrices. Estas reglas se aplican igualmente bien a otros tipos de objetos estáticos).
Miembros de datos de matriz
Los miembros de datos de matriz se crean cuando se crea su objeto propietario. Desafortunadamente, C ++ 03 no proporciona medios para inicializar matrices en la lista de inicializadores de miembros , por lo que la inicialización debe ser falsificada con asignaciones:
Alternativamente, puede definir una matriz automática en el cuerpo del constructor y copiar los elementos sobre:
En C ++ 0x, las matrices se pueden inicializar en la lista de inicializadores de miembros gracias a la inicialización uniforme :
Esta es la única solución que funciona con tipos de elementos que no tienen un constructor predeterminado.
Matrices dinámicas
Las matrices dinámicas no tienen nombres, por lo tanto, el único medio para acceder a ellas es a través de punteros. Como no tienen nombre, de ahora en adelante me referiré a ellos como "matrices anónimas".
En C, se crean matrices anónimas a través de
malloc
y amigos. En C ++, las matrices anónimas se crean utilizando lanew T[size]
sintaxis que devuelve un puntero al primer elemento de una matriz anónima:El siguiente arte ASCII muestra el diseño de la memoria si el tamaño se calcula como 8 en tiempo de ejecución:
Obviamente, las matrices anónimas requieren más memoria que las matrices con nombre debido al puntero adicional que debe almacenarse por separado. (También hay algunos gastos generales adicionales en la tienda gratuita).
Tenga en cuenta que no hay una descomposición de matriz a puntero aquí. Aunque la evaluación
new int[size]
de hecho crea una matriz de enteros, el resultado de la expresión yanew int[size]
es un puntero a un único entero (el primer elemento), no una matriz de enteros o un puntero a una matriz de enteros de tamaño desconocido. Eso sería imposible, porque el sistema de tipo estático requiere que los tamaños de matriz sean constantes de tiempo de compilación. (Por lo tanto, no anoté la matriz anónima con información de tipo estático en la imagen).Con respecto a los valores predeterminados para los elementos, las matrices anónimas se comportan de manera similar a las matrices automáticas. Normalmente, las matrices anónimas de POD no se inicializan, pero hay una sintaxis especial que desencadena la inicialización del valor:
(Observe el par de paréntesis final justo antes del punto y coma). Nuevamente, C ++ 0x simplifica las reglas y permite especificar valores iniciales para matrices anónimas gracias a la inicialización uniforme:
Si ha terminado de usar una matriz anónima, debe devolverla al sistema:
Debe liberar cada matriz anónima exactamente una vez y luego nunca volver a tocarla. Si no se libera en absoluto, se produce una pérdida de memoria (o, más generalmente, según el tipo de elemento, una pérdida de recursos), e intentar liberarlo varias veces se traduce en un comportamiento indefinido. Usar el formulario sin matriz
delete
(ofree
) en lugar dedelete[]
liberar la matriz también es un comportamiento indefinido .fuente
static
uso en el ámbito del espacio de nombres se eliminó en C ++ 11.new
que soy un operador, sin duda podría devolver la matriz localizada por referencia. Simplemente no tiene sentido ...new
es mucho más antiguo que las referencias.int a[10]; int (&r)[] = a;