multidimensional matriz examples empty declarar array 2x2 c++ arrays multidimensional-array dynamic-arrays

c++ - matriz - int[n][m], donde n y m son conocidos en tiempo de ejecución



declarar array multidimensional c++ (2)

¿Por qué no tener un std::vector de std::vector ''s?

std::vector<std::vector<int> > arr(n, std::vector<int>(m));

Accediendo a un artículo se convierte en:

std::cout << "(2,1) = " << arr[2][1] << std::endl;

A menudo necesito crear una matriz 2D con ancho y alto (que sean nym) desconocida en el momento de la compilación, generalmente escribo:

vector<int> arr(n * m);

Y accedo a elementos manualmente con:

arr[j * m + i]

Recientemente me dijeron que podía escribir en su lugar:

int arr[n][m] // n and m still only known at runtime.

Entonces aquí hay 2 preguntas:

  1. ¿Este comportamiento está permitido por el estándar de C ++?
  2. ¿Cómo debo pasar tal matriz a una función? g ++ informa que arr tiene tipo int (*)[n] , pero de nuevo, n es dinámico y no se conoce fuera de la función donde se declara ( main ).

La característica que está preguntando (donde las dimensiones solo se conocen durante el tiempo de ejecución) es una extensión no estándar de C ++, pero una estándar de C.99 (incluida en una característica opcional en C.11). La función se denomina matriz de longitud variable (VLA) y el enlace es la documentación para GCC.

Si está utilizando GCC, debe pasar la longitud de la matriz como parámetro de la función.

void foo (int m, int arr[][m]) { //... }

Sin embargo , parece que hay un error en el compilador o en la documentación, ya que la sintaxis del prototipo de la función anterior solo funciona al compilar el código C, no C ++ (a partir de la versión 4.8.2 de gcc). Lo único que encontré fue utilizar un parámetro void * y convertirlo en el cuerpo de la función:

int foo_workaround (int m, void *x) { int (*arr)[m] = static_cast<int (*)[m]>(x); //... }

Hay otras soluciones si no quiere confiar en una extensión de compilación. Si no le importa una asignación diferente para cada fila, puede usar un vector de vectores, por ejemplo:

std::vector<std::vector<int> > arr(n, std::vector<int>(m));

Sin embargo, si quiere un bloque de asignación único como el que demostró en su propio ejemplo, entonces es mejor crear una clase contenedora alrededor del vector para darle una sintaxis similar a 2-d.

template <typename T> class vector2d { int n_; int m_; std::vector<T> vec_; template <typename I> class vector2d_ref { typedef std::iterator_traits<I> TRAITS; typedef typename TRAITS::value_type R_TYPE; template <typename> friend class vector2d; I p_; vector2d_ref (I p) : p_(p) {} public: R_TYPE & operator [] (int j) { return *(p_+j); } }; typedef std::vector<T> VEC; typedef vector2d_ref<typename VEC::iterator> REF; typedef vector2d_ref<typename VEC::const_iterator> CREF; template <typename I> vector2d_ref<I> ref (I p, int i) { return p + (i * m_); } public: vector2d (int n, int m) : n_(n), m_(m), vec_(n*m) {} REF operator [] (int i) { return ref(vec_.begin(), i); } CREF operator [] (int i) const { return ref(vec_.begin(), i); } };

El operator[] la envoltura operator[] devuelve un objeto intermedio que también sobrecarga el operator[] para permitir la sintaxis de matriz bidimensional cuando se utiliza la envoltura.

vector2d<int> v(n, m); v[i][j] = 7; std::cout << v[i][j] << ''/n'';