c++ - matriz - matrices en programacion
Recuento de elementos de una matriz en C++ (9)
Digamos que tengo una matriz arr
. ¿Cuándo no daría lo siguiente el número de elementos de la matriz: sizeof(arr) / sizeof(arr[0])
?
Lo que puedo decir de un solo caso: la matriz contiene elementos que son de diferentes tipos derivados del tipo de la matriz.
¿Tengo razón y hay (estoy casi seguro de que debe haber) otros casos similares?
Lo siento por la pregunta trivial, soy un desarrollador de Java y soy bastante nuevo en C ++.
¡Gracias!
Digamos que tengo una matriz arr. ¿Cuándo no daría lo siguiente el número de elementos de la matriz:
sizeof(arr) / sizeof(arr[0])
?
En contextos donde arr
no es realmente la matriz (sino un puntero al elemento inicial). Otras respuestas explican cómo sucede esto.
Lo que puedo decir de un solo caso: la matriz contiene elementos que son de diferentes tipos derivados del tipo de la matriz.
Esto no puede suceder (porque, fundamentalmente, la misma razón por la que los arreglos Java no funcionan bien con los genéricos). La matriz se escribe estáticamente; reserva "ranuras" de memoria que están dimensionadas para un tipo específico (el tipo base).
Lo siento por la pregunta trivial, soy un desarrollador de Java y soy bastante nuevo en C ++.
Las matrices de C ++ no son objetos de primera clase. Puede usar boost :: array para hacer que se comporten más como matrices de Java, pero tenga en cuenta que todavía tendrá una semántica de valor en lugar de semántica de referencia, al igual que con todo lo demás. (En particular, esto significa que realmente no puede declarar una variable de tipo análogo a Foo[]
en Java, ni reemplazar una matriz con otra de un tamaño diferente; el tamaño de la matriz es una parte del tipo). Use .size()
con esta clase en la que .length
en Java. (También proporciona iteradores que proporcionan la interfaz habitual para los iteradores de C ++).
Digamos que tengo una matriz arr. ¿Cuándo no daría lo siguiente el número de elementos de la matriz: sizeof (arr) / sizeof (arr [0])?
Una cosa que he visto a menudo nuevos programadores haciendo esto:
void f(Sample *arr)
{
int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}
Sample arr[10];
f(arr);
Así que los nuevos programadores creen que el valor de count
será 10. Pero eso está mal.
Incluso esto está mal:
void g(Sample arr[]) //even more deceptive form!
{
int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10
}
Es todo porque una vez que pasas una matriz a cualquiera de estas funciones, se convierte en un tipo de puntero , por lo que sizeof(arr)
daría el tamaño de puntero , no de matriz.
EDITAR:
La siguiente es una forma elegante de pasar una matriz a una función, sin dejar que se desintegre en el tipo de puntero:
template<size_t N>
void h(Sample (&arr)[N])
{
size_t count = N; //N is 10, so would be count!
//you can even do this now:
//size_t count = sizeof(arr)/sizeof(arr[0]); it''ll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!
En primer lugar, puede evitar ese problema utilizando std::vector
lugar de una matriz. En segundo lugar, si coloca los objetos de una clase derivada en una matriz de una súper clase, experimentará el rebanado, pero la buena noticia es que su fórmula funcionará. Las colecciones polimórficas en C ++ se logran utilizando punteros. Hay tres opciones principales aquí:
- punteros normales
- una colección de
boost::shared_ptr
- un contenedor Boost.Pointer
Las matrices en C ++ son muy diferentes de las de Java en que están completamente sin administrar. El compilador o el tiempo de ejecución no tienen idea de qué tamaño es la matriz.
La información solo se conoce en tiempo de compilación si el tamaño está definido en la declaración:
char array[256];
En este caso, sizeof (array) le da el tamaño adecuado.
Sin embargo, si usa un puntero como una matriz, la "matriz" solo será un puntero, y sizeof no le dará ninguna información sobre el tamaño real de la matriz.
STL ofrece una gran cantidad de plantillas que le permiten tener matrices, algunas de ellas con información sobre el tamaño, algunas de ellas con tamaños variables, y la mayoría con buenos accesores y control de límites.
No hay casos en los que, dada una matriz arr
, el valor de sizeof(arr) / sizeof(arr[0])
no sea el recuento de elementos, según la definición de array y sizeof
.
De hecho, incluso se menciona directamente (§5.3.3 / 2):
.... Cuando se aplica a una matriz, el resultado es el número total de bytes en la matriz. Esto implica que el tamaño de una matriz de n elementos es n veces el tamaño de un elemento.
Énfasis mío. Divida por el tamaño de un elemento, sizeof(arr[0])
, para obtener n .
No, eso seguiría produciendo el valor correcto porque debe definir la matriz para que sea todos los elementos de un solo tipo o los punteros a un tipo. En cualquier caso, el tamaño de la matriz se conoce en tiempo de compilación, por lo que sizeof (arr) / sizeof (arr [0]) siempre devuelve el recuento de elementos.
Aquí hay un ejemplo de cómo usar esto correctamente:
int nonDynamicArray[ 4 ];
#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )
Iré uno más aquí para mostrar cuándo usar esto correctamente. No lo usarás muy a menudo. Es principalmente útil cuando desea definir una matriz específicamente para que pueda agregarle elementos sin cambiar mucho el código más adelante. Es una construcción que es principalmente útil para el mantenimiento . El ejemplo canónico (cuando lo pienso de todos modos ;-) es crear una tabla de comandos para algún programa al que intenta agregar más comandos más adelante. En este ejemplo para mantener / mejorar su programa, todo lo que necesita hacer es agregar otro comando a la matriz y luego agregar el controlador de comandos:
char *commands[] = { // <--- note intentional lack of explicit array size
"open",
"close",
"abort",
"crash"
};
#define kCommandsCount ( sizeof(commands) / sizeof(commands[ 0 ]) )
void processCommand( char *command ) {
int i;
for ( i = 0; i < kCommandsCount; ++i ) {
// if command == commands[ i ] do something (be sure to compare full string)
}
}
Sé que es un tema antiguo, pero ¿qué pasa con una solución simple como while loop?
int function count(array[]) {
int i = 0;
while(array[i] != NULL) {
i++;
}
return i;
}
Sé que es más lento que sizeof () pero este es otro ejemplo de conteo de matriz.
Utilice la macro "_countof (array)" de Microsoft. Este enlace a Microsoft Developer Network lo explica y ofrece un ejemplo que demuestra la diferencia entre "sizeof (array)" y la macro "_countof (array)".
_countof (my_array) en MSVC
Lo que puedo decir de un solo caso: la matriz contiene elementos que son de diferentes tipos derivados del tipo de la matriz.
Los elementos de una matriz en C ++ son objetos, no punteros, por lo que no puede tener un objeto de tipo derivado como un elemento.
Y como se mencionó anteriormente, sizeof (my_array) (como _countof () también) funcionará solo en el alcance de la definición de matriz.