c++ - tipo - Ahora que tenemos std:: array ¿qué usos quedan para las matrices estilo C?
manejo de arrays en java (7)
- para implementar algo como
std::array
- si no quiere usar el STL o no puede
- Para el rendimiento
std::array
es muy superior a las matrices en C. E incluso si quiero interoperar con el código heredado, solo puedo usar std::array::data()
. ¿Hay alguna razón por la que alguna vez quisiera un conjunto de la vieja escuela?
A menos que me haya perdido algo (no he seguido los cambios más recientes en el estándar demasiado de cerca), la mayoría de los usos de las matrices de estilo C aún permanecen. std::array
permite la inicialización estática, pero aún no contará los inicializadores por usted. Y dado que el único uso real de matrices de estilo C antes de std::array
fue para tablas inicializadas estáticamente a lo largo de las líneas de:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
utilizando las funciones habituales de plantilla de begin
y end
(adoptadas en C ++ 11) para iterar sobre ellas. Sin mencionar el tamaño, que el compilador determina a partir del número de inicializadores.
EDITAR: Otra cosa que olvidé: los literales de cadena siguen siendo matrices de estilo C; es decir, con el tipo char[]
. No creo que nadie excluya el uso de literales de cadenas simplemente porque tenemos std::array
.
Como dijo Sumant, las matrices multidimensionales son mucho más fáciles de usar con las matrices C integradas que con std::array
.
Cuando está anidado, std::array
puede volverse muy difícil de leer e innecesariamente detallado.
Por ejemplo:
std::array<std::array<int, 3>, 3> arr1;
comparado con
char c_arr[3][3];
Además, tenga en cuenta que begin()
, end()
y size()
devuelven valores sin sentido cuando anida std::array
.
Por estas razones, he creado mis propios contenedores de matriz multidimensional de tamaño fijo, array_2d
y array_3d
. Son análogos a std::array
pero para matrices multidimensionales de 2 y 3 dimensiones. Son más seguros y no tienen un rendimiento peor que los arreglos multidimensionales incorporados. No incluí un contenedor para matrices multidimensionales con dimensiones superiores a 3 ya que son poco comunes. En C ++ 0x, se podría hacer una versión de plantilla variadica que soporte un número arbitrario de dimensiones.
Un ejemplo de la variante bidimensional:
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> my2darr = {{
{ 32.19, 47.29, 31.99, 19.11, 11.19},
{ 11.29, 22.49, 33.47, 17.29, 5.01 },
{ 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
La documentación completa está disponible aquí:
http://fsma.googlecode.com/files/fsma.html
Puede descargar la biblioteca aquí:
Los arreglos de estilo C que están disponibles en C ++ son en realidad mucho menos versátiles que los C-arrays reales. La diferencia es que en C, los tipos de matriz pueden tener tamaños de tiempo de ejecución . El siguiente es un código C válido, pero no se puede expresar con arreglos C-style C ni con los tipos C ++ array<>
:
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
En C ++, tendría que asignar la matriz temporal en el montón:
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
Esto no se puede lograr con std::array<>
, porque la bar
no se conoce en tiempo de compilación, requiere el uso de matrices de estilo C en C ++ o de std::vector<>
.
Mientras que el primer ejemplo podría expresarse con relativa facilidad en C ++ (aunque requiriendo new[]
y delete[]
), no se puede lograr lo siguiente en C ++ sin std::vector<>
:
void smoothImage(int width, int height, int (*pixels)[width]) {
int (*copy)[width] = malloc(height*sizeof(*copy));
memcpy(copy, pixels, height*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y][x] = //compute smoothed value based on data around copy[y][x]
}
}
free(copy);
}
El punto es que los punteros a los arreglos lineales int (*)[width]
no pueden usar un ancho de tiempo de ejecución en C ++, lo que hace que cualquier código de manipulación de imágenes sea mucho más complicado en C ++ que en C. Una implementación C ++ típica de la imagen ejemplo de manipulación se vería así:
void smoothImage(int width, int height, int* pixels) {
int* copy = new int[height*width];
memcpy(copy, pixels, height*width*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
}
}
delete[] copy;
}
Este código hace exactamente los mismos cálculos que el código C anterior, pero necesita realizar el cálculo del índice a mano donde se usan los índices . Para el caso 2D, esto todavía es factible (a pesar de que tiene muchas oportunidades para hacer que el cálculo del índice sea incorrecto). Sin embargo, se pone realmente desagradable en el caso 3D.
Me gusta escribir código en C ++. Pero cada vez que necesito manipular datos multidimensionales, realmente me pregunto si debería mover esa parte del código a C.
No, para decirlo sin rodeos. Y en 30 personajes.
Por supuesto, necesitas matrices en C para implementar std::array
, pero esa no es realmente una razón por la que un usuario quiera alguna vez matrices en C. Además, no, std::array
no es menos eficiente que una matriz C, y tiene una opción para un acceso controlado por límites. Y, por último, es completamente razonable que cualquier programa C ++ dependa de la biblioteca estándar (ese es el punto de que es estándar) y si no tiene acceso a una biblioteca estándar, entonces su compilador no es conforme y el la pregunta está etiquetada como "C ++", no como "C ++ y las cosas que no son C ++ que omiten la mitad de la especificación porque la consideraron inapropiada".
Parece que usar matrices multidimensionales es más fácil con matrices C que std::array
. Por ejemplo,
char c_arr[5][6][7];
Opuesto a
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
También debido a la propiedad de decaimiento automático de las matrices C, c_arr[i]
en el ejemplo anterior decaerá en un puntero y solo tendrá que pasar las dimensiones restantes como dos parámetros más. Mi punto es que c_arr
no es costoso de copiar. Sin embargo, cpp_arr[i]
será muy costoso de copiar.
Puede ser el std::array
no es lento. Pero hice algunos benchmarking usando simple store y leí desde std :: array; Consulte los resultados de la evaluación comparativa a continuación (en W8.1, VS2013 Actualización 4):
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
De acuerdo con las marcas negativas, el código que utilicé está en el pastebin ( link )
El código de clase de referencia está here ;
No sé mucho sobre benchmarks ... Mi código puede estar defectuoso