¿Cómo podría asignar dinámicamente una matriz multidimensional?Arrays multidimensionales en C++ en el montón
Respuesta
Si se conoce el tamaño de las dimensiones anidadas ya, también puede asignar literalmente una matriz multidimensional utilizando nueva:
typedef int dimensions[3][4];
dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;
en lugar de 10
, un valor determinado de tiempo de ejecución se puede pasar. Como no es parte del operador nuevo, está permitido. Esto es bueno si conoce el número de columnas, pero desea mantener la cantidad de filas variables, por ejemplo. El typedef hace que sea más fácil leer el código.
No borrar [] [] [] dim? ;-) –
esta respuesta es desagradable: http://stackoverflow.com/questions/198051/why-delete-multidimensionalarray-operator-in-c-does-not-exist#326338, pero espero que responda a sus inquietudes :) –
Nice one, litb. No tenía idea de que pudieras hacer eso. –
Aquí está la implementación que tengo; Declaro un solo bloque contiguo de int
s en lugar de crear nuevos bloques dentro de mi ciclo for, así que no estoy causando fallas en las páginas por todos lados. Gracias a eJames por señalar por qué este código se rompió originalmente.
int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];
for (int i = 0; i < height; ++i)
{
myArray[i] = data + (i*width);
}
// do some things here
delete[] data;
delete[] myArray;
Este código no funcionará como se muestra. Específicamente, las escrituras en myArray [i] en su ciclo estarán por todos lados. Ver mi bucle modificado aquí: http://stackoverflow.com/questions/340943/c-multi-dimensional-arrays-on-the-heap#341008 –
Su bucle no escribiría correctamente los valores del puntero en myArray
. Yo sugeriría que el siguiente en su lugar:
int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
myArray[i] = index;
index += height;
}
// ...
delete[] data;
delete[] myArray;
Tienes razón; Lo hice funcionar y lo refactoré sin verificar si funciona. Tal vez debería dejar de romper la compilación ... – eplawless
ver esto: "¿Cómo asigno matrices multidimensionales utilizando las nuevas" C++ FAQ by Marshall Cline
Ver y "¡Pero el código de las preguntas frecuentes anterior es muy complicado y propenso a errores! ¿No hay una manera más simple?" secciones
No he pensado en las preguntas frecuentes sobre C++ en algún momento. Junto con el libro de Strostrup, solía ser una de mis lecturas de programación favoritas. – Rich
Preguntas frecuentes [16.16] no parece ser correcto. Asigna memoria para filas usando new []. Luego establece cada puntero a NULL y lo reasigna. Nunca desasigna la memoria que establece en NULL y, por lo tanto, pierde esa memoria. Por favor, compruebe. – user236215
std::vector<std::vector<int> >
se debe mencionar, ya que a menudo es la forma más sencilla. Sin embargo, tenga en cuenta que no es rectangular. No todos los std::vector<int>
deben tener la misma longitud.
Para una matriz unidimensional es más simple, pero dos dimensiones complican las cosas. Debe inicializar explícitamente cada elemento al tamaño que desea que sea. –
Es cierto, pero eso no es arduo: std :: vector
Para completar, aquí hay una mejor manera de hacerlo en C++ cuando conoces los límites de la matriz antes de tiempo. El beneficio de utilizar la siguiente clase es que no tiene que preocuparse por llamar a delete [] en sus datos. Esto significa que esta clase será a prueba de excepciones, y todas las otras cosas geniales sobre RAII.
template<typename T, int width, int height>
class MultiArray
{
private:
typedef T cols[height];
cols * data;
public:
T& operator() (int x, int y) { return data[x][y]; }
MultiArray() { data = new cols[width]; }
~MultiArray() { delete [] data; }
};
Uso:
MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);
edición: y, mientras yo estoy en ello, aquí es la configuración que puede utilizar si no lo hace conocer los límites de la matriz hasta el tiempo de ejecución:
template<typename T>
class Array2D
{
private:
const int width;
T * data;
public:
T& operator() (int x, int y) { return data[y*width + x]; }
Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
~Array2D() { delete [] data; }
};
Uso:
Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
Puede indexar una dimensión como una dimensional de 2, 3 o N si solo tiene espacio sobre la cantidad correcta de elementos. Por ejemplo, si tengo 10 filas y 10 columnas, sé que si estoy en la fila 3 tendré que revisar al menos 30 elementos para acceder a ella.
De alguna manera prefiero esta notación para matrices 2D simples ya que no tengo que preocuparme por los niveles anidados de los punteros. La desventaja es la notación del índice más desordenado.He aquí un ejemplo de una matriz 2D con n filas ym columnas:
int *matrix = new int[n*m];
//set element (3,7) to 10
matrix[3*m+7] = 10;
//print the matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << matrix[i*m+j] << ' ';
}
cout << '\n';
}
Me sorprende que nadie ha mencionado boost::multi_array
todavía. Necesitaba un arreglo en 2D en un programa la semana pasada, y descubrí que era mucho más fácil y más rápido de codificar que las soluciones caseras que he encontrado antes (todas mencionadas en otros comentarios) .
Mi pregunta here cubre en su mayoría el mismo tema bastante bien gracias a algunas respuestas excelentes. Sin embargo, no cubre matrices N-Dimensionales, que tampoco he visto abordar en las respuestas aquí, pero eso sería útil.
¿Qué le parece usar Boost.Multiarray? ¡Creo que responde bastante bien a tu necesidad! http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction
Aquí es un extracto de la página de documentación:
#include <boost/multi_array.hpp>
#include <cassert>
int main()
{
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array< double, 3 > array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
Como otra alternativa, STLSoft incluye una clase fixed_array_2d (así como versiones 3D y 4D). En comparación con las soluciones caseras proporcionadas aquí, tiene una implementación similar pero un conjunto de características más completo (soporte completo para iteradores, etc.). Comparado con boost :: multi_array, es más liviano y más fácil en compiladores de C++ que no cumplen con los requisitos, pero (intencionalmente) carece de algunas de las características de multi_array.
Esta es una reproducción de una publicación en otro hilo. Hace exactamente lo que quiere, sin necesidad de conocer las dimensiones de la matriz antes de tiempo, y sin usar boost o STL.
Aquí hay una rutina que asigna la matriz 3D de la dimensión N1 x N2 x N3 en el espacio contiguo de la memoria al mismo tiempo que le permite la sintaxis a [i] [j] [k] para el acceso del operador. La matriz es dinámica pero continua, por lo que es una gran ventaja sobre el vector <> enfoque y bucles de llamadas nuevas [].
template <class T> T ***Create3D(int N1, int N2, int N3)
{
T *** array = new T ** [N1];
array[0] = new T * [N1*N2];
array[0][0] = new T [N1*N2*N3];
int i,j,k;
for(i = 0; i < N1; i++) {
if (i < N1 -1) {
array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);
array[i+1] = &(array[0][(i+1)*N2]);
}
for(j = 0; j < N2; j++) {
if (j > 0) array[i][j] = array[i][j-1] + N3;
}
}
cout << endl;
return array;
};
template <class T> void Delete3D(T ***array) {
delete[] array[0][0];
delete[] array[0];
delete[] array;
};
Y más tarde en su rutina de ejecución ...
int *** array3d;
int N1=4, N2=3, N3=2;
int elementNumber = 0;
array3d = Create3D<int>(N1,N2,N3);
//equivalently, a 'flat' array could be obtained with
//int * array = array3d[0][0];
cout << "{" << endl;
for (i=0; i<N1; i++) {
cout << "{";
for (j=0; j<N2; j++) {
cout << "{";
for (k=0; k<N3; k++) {
array3d[i][j][k] = elementNumber++;
cout << setw(4) << array3d[i][j][k] << " ";
//or if you're using the flat array:
//array[i*N2*N3 + j*N3 + k] = elementNumber++;
}
cout << "}";
}
cout << "}";
cout << endl ;
}
cout << "}" << endl;
Delete3D(array3d);
proporciona la salida:
{
{{ 0 1 }{ 2 3 }{ 4 5 }}
{{ 6 7 }{ 8 9 }{ 10 11 }}
{{ 12 13 }{ 14 15 }{ 16 17 }}
{{ 18 19 }{ 20 21 }{ 22 23 }}
}
- 1. Arrays multidimensionales en Bash
- 2. Arrays multidimensionales PostgreSQL en SQLAlchemy
- 3. Arrays multidimensionales C++ de alto rendimiento
- 4. Arrays multidimensionales vía ajax a PHP
- 5. Arrays asociativos en C
- 6. Arrays tipo C en perl
- 7. matrices multidimensionales en una estructura en C#
- 8. ¿Cómo comparar matrices multidimensionales en C#?
- 9. C# Dictionary of arrays
- 10. Arrays C++ y make_unique
- 11. seguridad de rosca en arrays de C#
- 12. POST'ing arrays en WebClient (C# /. Net)
- 13. espacio en el montón de Java en netbeans ... ¡pero ya he aumentado el tamaño del montón!
- 14. ¿Cómo manejo mejor las matrices multidimensionales dinámicas en C/C++?
- 15. ¿Es una mala práctica utilizar matrices multidimensionales en C/C++?
- 16. ¿Puede un objeto asignado en el montón const en C++?
- 17. Implantar y explotar matrices multidimensionales
- 18. definir montón de métodos estáticos en C++
- 19. ¿Fibonacci, binario o montón binomial en C#?
- 20. Objetos asignados en el montón
- 21. Eliminación en el montón binario
- 22. Redimming arrays en VBA
- 23. C++ Etiqueta sobre las variables de miembro en el montón
- 24. C++ - La asignación de memoria en el montón usando "nueva"
- 25. para declarar variables miembro en el montón de C++
- 26. Usando numpy.argmax() en matrices multidimensionales
- 27. eficiente System.arraycopy en matrices multidimensionales
- 28. Inicialización matrices multidimensionales en C# (con otros arreglos)
- 29. conversión de matrices multidimensionales a los punteros en C++
- 30. Mueva datos de una lista de arrays a otra lista de arrays en C#
Aaah, esta es una buena pregunta. –