Notas de C ++: Array Initialization tiene una buena lista sobre la inicialización de arrays. tengo un
int array[100] = {-1};
esperando que esté lleno con -1's pero no, solo el primer valor es y el resto son 0's mezclados con valores aleatorios.
El código
int array[100] = {0};
funciona bien y establece cada elemento en 0.
¿Qué me estoy perdiendo aquí? ¿No se puede inicializar si el valor no es cero?
Y 2: ¿La inicialización predeterminada (como arriba) es más rápida que el ciclo habitual a través de toda la matriz y asigna un valor o hace lo mismo?
{0}
No es un caso especial para estructuras ni matrices. La regla es que los elementos sin inicializador se inicializan como si tuvieran0
un inicializador. Si hay agregados anidados (pstruct x array[100]
. Ej. ), Los inicializadores se aplican a los no agregados en orden "mayor de filas"; Opcionalmente, se pueden omitir llaves para hacer esto.struct x array[100] = { 0 }
es válido en C; y válido en C ++ siempre que el primer miembro destruct X
acepte0
como inicializador.{ 0 }
no es especial en C, pero es mucho más difícil definir un tipo de datos que no se pueda inicializar con él, ya que no hay constructores y, por lo tanto, no hay forma de evitar que0
se conviertan y se asignen implícitamente a algo .Respuestas:
Usando la sintaxis que usaste,
dice "establecer el primer elemento en
-1
y el resto en0
" ya que todos los elementos omitidos se establecen en0
.En C ++, para configurarlos a todos
-1
, puede usar algo comostd::fill_n
(desde<algorithm>
):En C portátil, tienes que rodar tu propio bucle. Hay extensiones de compilador o puede confiar en el comportamiento definido por la implementación como un acceso directo si eso es aceptable.
fuente
#include <algorithm>
el encabezado correcto,<vector>
puede o no incluirlo indirectamente, eso dependería de su implementación.int
s y expandirla al inicializador de la matriz.fill_n
para llenar una matriz 2D completa. Necesita recorrer una dimensión, mientras completa la otra.std::fill_n
No es inicialización.Hay una extensión para el compilador gcc que permite la sintaxis:
Esto establecería todos los elementos en -1.
Esto se conoce como "inicializadores designados". Consulte aquí para obtener más información.
Tenga en cuenta que esto no está implementado para el compilador gcc c ++.
fuente
La página a la que enlazó ya dio la respuesta a la primera parte:
No hay una forma integrada de inicializar toda la matriz a un valor distinto de cero.
En cuanto a cuál es más rápido, se aplica la regla habitual: "El método que le da al compilador la mayor libertad es probablemente más rápido".
simplemente le dice al compilador "establezca estos 100 ints a cero", que el compilador puede optimizar libremente.
Es mucho más específico. Le dice al compilador que cree una variable de iteración
i
, le dice el orden en que deben inicializarse los elementos, y así sucesivamente. Por supuesto, es probable que el compilador optimice eso, pero el punto es que aquí está especificando en exceso el problema, obligando al compilador a trabajar más duro para obtener el mismo resultado.Finalmente, si desea establecer la matriz en un valor distinto de cero, debe (al menos en C ++) usar
std::fill
:Una vez más, podría hacer lo mismo con una matriz, pero esto es más conciso y le da al compilador más libertad. Solo está diciendo que desea que toda la matriz se llene con el valor 42. No dice nada sobre el orden en que debe hacerse, ni nada más.
fuente
C ++ 11 tiene otra opción (imperfecta):
fuente
std::fill(begin(a), end(a), -1)
Con {} asigna los elementos a medida que se declaran; el resto se inicializa con 0.
Si no hay
= {}
que iniciar, el contenido no está definido.fuente
La página que vinculaste
Problema de velocidad: cualquier diferencia sería insignificante para matrices tan pequeñas. Si trabaja con matrices grandes y la velocidad es mucho más importante que el tamaño, puede tener una matriz constante de los valores predeterminados (inicializados en el momento de la compilación) y luego
memcpy
llevarlos a la matriz modificable.fuente
Otra forma de inicializar la matriz a un valor común, sería generar realmente la lista de elementos en una serie de definiciones:
La inicialización de una matriz a un valor común se puede hacer fácilmente:
Nota: DUPx introducido para habilitar la sustitución de macros en los parámetros de DUP
fuente
Para el caso de una matriz de elementos de un solo byte, puede usar memset para establecer todos los elementos en el mismo valor.
Hay un ejemplo aquí .
fuente
Utilizando
std::array
, podemos hacer esto de una manera bastante sencilla en C ++ 14. Es posible hacerlo solo en C ++ 11, pero un poco más complicado.Nuestra interfaz tiene un tamaño de tiempo de compilación y un valor predeterminado.
La tercera función es principalmente por conveniencia, por lo que el usuario no tiene que construir una
std::integral_constant<std::size_t, size>
, ya que es una construcción bastante prolija. El verdadero trabajo lo realiza una de las dos primeras funciones.La primera sobrecarga es bastante sencilla: construye una
std::array
de tamaño 0. No es necesario copiar, solo la construimos.La segunda sobrecarga es un poco más complicada. Reenvía el valor que obtuvo como fuente, y también construye una instancia de
make_index_sequence
y solo llama a alguna otra función de implementación. ¿Cómo se ve esa función?Esto construye los argumentos del primer tamaño - 1 copiando el valor que pasamos. Aquí, usamos nuestros índices de paquete de parámetros variables como algo para expandir. Hay entradas de tamaño - 1 en ese paquete (como especificamos en la construcción de
make_index_sequence
), y tienen valores de 0, 1, 2, 3, ..., tamaño - 2. Sin embargo, no nos importan los valores ( así que lo anulamos, para silenciar cualquier advertencia del compilador). La expansión del paquete de parámetros expande nuestro código a algo como esto (suponiendo que size == 4):Usamos esos paréntesis para garantizar que la expansión del paquete variable
...
expanda lo que queremos, y también para asegurarnos de que estamos utilizando el operador de coma. Sin los paréntesis, parecería que estamos pasando un montón de argumentos a la inicialización de nuestra matriz, pero realmente, estamos evaluando el índice, convirtiéndolo en nulo, ignorando ese resultado nulo y luego devolviendo el valor, que se copia en la matriz .El argumento final, el que invocamos
std::forward
, es una optimización menor. Si alguien pasa una cadena std :: temporal y dice "haga una matriz de 5 de estos", nos gustaría tener 4 copias y 1 movimiento, en lugar de 5 copias. Elstd::forward
asegura que hacemos esto.El código completo, incluidos los encabezados y algunas pruebas unitarias:
fuente
non_copyable
tipo es realmente copiable por medio deoperator=
.non_copy_constructible
que sería un nombre más preciso para el objeto. Sin embargo, no hay ninguna asignación en este código, por lo que no importa para este ejemplo.1) Cuando usa un inicializador, para una estructura o una matriz como esa, los valores no especificados se construyen esencialmente por defecto. En el caso de un tipo primitivo como ints, eso significa que se pondrán a cero. Tenga en cuenta que esto se aplica de forma recursiva: podría tener una matriz de estructuras que contienen matrices y si especifica solo el primer campo de la primera estructura, todo el resto se inicializará con ceros y constructores predeterminados.
2) El compilador probablemente generará un código de inicializador que es al menos tan bueno como podría hacerlo a mano. Tiendo a preferir dejar que el compilador haga la inicialización por mí, cuando sea posible.
fuente
En C ++, también es posible usar meta programación y plantillas variadas. La siguiente publicación muestra cómo hacerlo: mediante programación, cree matrices estáticas en tiempo de compilación en C ++ .
fuente
En el lenguaje de programación C ++ V4, Stroustrup recomienda el uso de vectores o valarrays sobre matrices integradas. Con valarrary's, cuando los crea, puede iniciarlos a un valor específico como:
Para inicializar una matriz de 7 miembros con "7777777".
Esta es una forma de C ++ de implementar la respuesta usando una estructura de datos C ++ en lugar de una matriz "C simple".
Cambié a usar el valarray como un intento en mi código para tratar de usar C ++ 'isms v. C'isms ...
fuente
Debería ser una característica estándar, pero por alguna razón no está incluida en el estándar C ni en C ++ ...
En Fortran puedes hacer:
pero no tiene números sin signo ...
¿Por qué C / C ++ no puede simplemente implementarlo? ¿Es realmente tan difícil? Es tan tonto tener que escribir esto manualmente para lograr el mismo resultado ...
¿Qué pasa si se trata de una matriz de 1,000,00 bytes? Necesitaría escribir un script para escribirlo o recurrir a hacks con ensamblaje / etc. Esto no tiene sentido.
Es perfectamente portátil, no hay razón para que no esté en el idioma.
Solo piratea como:
Una forma de hackearlo es mediante el preprocesamiento ... (El código a continuación no cubre casos extremos, pero está escrito para demostrar rápidamente lo que se puede hacer).
fuente
memset
, incluso con la matriz "codificada".