vectores tamaño sirven que punteros puntero programacion para maximo matrices los declaracion arreglos arreglo c++ arrays

tamaño - ¿Cómo lidiar con matrices(declaradas en la pila) en C++?



tamaño maximo de un arreglo en c (5)

Pensé que matrix_ sería esencialmente lo mismo que un doble **

En C hay verdaderas matrices multidimensionales, no matrices de punteros a matrices, por lo que un doble [4] [4] es una matriz contigua de cuatro matrices dobles [4], equivalentes a un doble [16], no a (doble *) [4].

No hay conversiones a tipos de matriz, aunque hay conversiones a referencias o punteros a matrices Al lanzar un valor a un doble [4] [4] se intentaría construir uno en la pila, equivalente a std :: string (parser.getMatrix ( )), excepto que la matriz no proporciona un constructor adecuado. Probablemente no quisiste hacer eso, incluso si pudieras.

Como el tipo codifica la zancada, necesita un tipo completo (el doble [] [] no funcionará). Puede reinterpretar emitir el vacío * a ((doble [4] [4]) *), y luego tomar la referencia. Pero es más fácil escribir la matriz y devolver una referencia del tipo correcto en primer lugar:

typedef double matrix_t[4][4]; class Parser { double matrix_[4][4]; public: void* get_matrix () { return static_cast<void*>(matrix_); } const matrix_t& get_matrix_ref () const { return matrix_; } }; int main () { Parser p; matrix_t& data1 = *reinterpret_cast<matrix_t*>(p.get_matrix()); const matrix_t& data2 = p.get_matrix_ref(); }

Tengo una clase para analizar una matriz que mantiene el resultado en un miembro de la matriz:

class Parser { ... double matrix_[4][4]; };

El usuario de esta clase necesita llamar a una función API (como en, una función que no tengo control, por lo que no puedo simplemente cambiar su interfaz para que las cosas funcionen más fácilmente) que se ve así:

void api_func(const double matrix[4][4]);

La única forma en que se me ocurrió que la persona que llama pase el resultado de la matriz a la función es haciendo que el miembro sea público:

void myfunc() { Parser parser; ... api_func(parser.matrix_); }

¿Es esta la única forma de hacer las cosas? Estoy asombrado de cómo las matrices multidimensionales inflexibles declaradas así son. Pensé que matrix_ sería esencialmente lo mismo que un double** y que podría lanzar (con seguridad) entre los dos. Como resultado, ni siquiera puedo encontrar una forma insegura de lanzar entre las cosas. Digamos que agregué un acceso a la clase Parser :

void* Parser::getMatrix() { return (void*)matrix_; }

Esto se compilará, pero no puedo usarlo, porque no parece haber una forma de volver al tipo de arreglo raro:

// A smorgasbord of syntax errors... api_func((double[][])parser.getMatrix()); api_func((double[4][4])parser.getMatrix()); api_func((double**)parser.getMatrix()); // cast works but it''s to the wrong type

El error es:

error C2440: ''type cast'': no ​​se puede convertir de ''void *'' a ''const double [4] [4]''

... con un apéndice intrigante:

No hay conversiones a tipos de matriz, aunque hay conversiones a referencias o punteros a matrices

No puedo determinar cómo lanzar a una referencia o un puntero a la matriz tampoco, aunque probablemente no me ayude aquí.

Para estar seguros, en este punto el asunto es puramente académico, ya que los void* son apenas más limpios que lo que un miembro de la clase deja en público.


Aquí hay una manera agradable y limpia:

class Parser { public: typedef double matrix[4][4]; // ... const matrix& getMatrix() const { return matrix_; } // ... private: matrix matrix_; };

Ahora está trabajando con un nombre de tipo descriptivo en lugar de una matriz, pero dado que es un typedef el compilador aún permitirá pasarlo a la función API inmutables que toma el tipo base.


He usado una unión como esta para pasar matrices en el pasado:

union matrix { double dflat[16]; double dmatr[4][4]; };

Luego pasa un puntero a tu setter y copia los datos en la matriz de tu clase.

Hay formas de manejar esto de otra manera (que son más genéricas), pero esta solución tiende a ser la más limpia al final, en mi experiencia.


Para elaborar sobre la respuesta seleccionada, observe esta línea

const matrix& getMatrix() const

Esto es genial, no tienes que preocuparte por los punteros y el casting. Está devolviendo una referencia al objeto matriz subyacente. Las referencias en mi humilde opinión son una de las mejores características de C ++, que echo de menos al codificar en C.

Si no está familiarizado con la diferencia entre referencias y punteros en C ++, lea esto

En cualquier caso, debe tener en cuenta que si el objeto Parser que posee realmente el objeto matriz subyacente queda fuera del alcance, cualquier código que intente acceder a la matriz a través de esa referencia se referirá a un objeto fuera del alcance, y te estrellarás


Prueba esto. Se compila limpiamente en gcc 4.1.3:

typedef double FourSquare[4][4]; class Parser { private: double matrix_[4][4]; public: Parser() { for(int i=0; i<4; i++) for(int j=0; j<4; j++) matrix_[i][j] = i*j; } public: const FourSquare& GetMatrix() { return matrix_; } }; void api_func( const double matrix[4][4] ) { } int main( int argc, char** argv ) { Parser parser; api_func( parser.GetMatrix() ); return 0; }