C++ pasa una matriz por referencia

7 minutos de lectura

C pasa una matriz por referencia
kiriloff

¿Está permitido pasar una matriz por referencia?

 void foo(double& *bar) 

Parece que mi compilador dice que no. ¿Por qué? ¿Cuál es la forma correcta de pasar una matriz por referencia? ¿O un trabajo alrededor? Tengo un argumento de matriz que mi método debería modificar y que debería recuperar después. Alternativamente, podría convertir esta matriz en un miembro de clase, lo que funciona bien, pero tiene muchos inconvenientes para otras partes de mi código (que me gustaría evitar).

Gracias y saludos.

  • Comprobar el regla espiral en el sentido de las agujas del reloj.

    – Un tipo programador

    4 de abril de 2012 a las 9:03

  • ¿Has considerado usar un std::vector ¿o similar?

    – mooooooooooooooooooooooo

    4 de abril de 2012 a las 9:06

  • @moooeeeeep std::vector es obviamente superior si el tamaño es dinámico/desconocido, pero en los casos en que el tamaño es siempre el mismo, sería excesivo, y en su lugar std::array resuelve la fealdad sintáctica al mismo tiempo que confiere valor semántico.

    – subrayado_d

    11 de diciembre de 2018 a las 11:52

  • también mirar en es.cppreference.com/w/cpp/utility/funcional/reference_wrapper

    – sdevikar

    25 de marzo de 2019 a las 15:46

  • ¿por qué no simplemente anular foo (doble barra[ ]) ? si lo desea, también puede proporcionar la longitud de la matriz como void foo (doble barra[2]). A menos que para un tipo complejo se deba evitar un constructor de copias.

    – causa última

    5 de noviembre de 2019 a las 0:30


1646958669 634 C pasa una matriz por referencia
jrok

Las matrices solo se pueden pasar por referencia, en realidad:

void foo(double (&bar)[10])
{
}

Esto le impide hacer cosas como:

double arr[20];
foo(arr); // won't compile

Para poder pasar una matriz de tamaño arbitrario a fooconviértalo en una plantilla y capture el tamaño de la matriz en tiempo de compilación:

template<typename T, size_t N>
void foo(T (&bar)[N])
{
    // use N here
}

Deberías considerar seriamente usar std::vectoro si tiene un compilador compatible con c++11, std::array.

  • “Sin embargo, una vez pasado a foola matriz decae a puntero”. No, no lo hace, y dado que solo puede pasar una matriz de 10 elementos, no necesita más información sobre el tamaño. (Y una vez más, usted no poder pasar una matriz a void foo( double*& ); los resultados de una conversión implícita es un valor r y no se puede utilizar para inicializar una referencia a no const. Debes usar void foo( double *const & );.

    – James Kanze

    4 de abril de 2012 a las 9:40

  • genial 🙂 esto es exactamente lo que estoy buscando. estaba haciendo void foo(T &bar[N]) en mi plantilla, pero eso en realidad significa “una matriz de referencias” y no “referencia a una matriz”.

    – OLL

    5 de noviembre de 2015 a las 11:23

  • Si tal función ya existe, y todo lo que tiene es un std::vector (del tamaño correcto), ¿cómo proyectaría el contenido del vector (quizás obtenido a través de std::vector::data()) a este tipo de matriz? ¿Cuál es la sintaxis para un tamaño de matriz fijo en un parámetro de tipo (es decir, para usar con static_cast<>)?

    – davidA

    14 de agosto de 2017 a las 2:52

  • @meowsqueak No lo harías, porque el elenco tendría un comportamiento indefinido, AFAICT; No puedo ver ninguna asignación hecha en reinterpret_cast para tratar una matriz asignada dinámicamente (sin tamaño intrínseco después de la asignación) como automática con tamaño fijo. Además, esa es la pregunta incorrecta: la pregunta correcta sería ‘¿Cómo puedo refactorizar mi código para que funcione con ambos tipos de contenedores?’, y la respuesta es plantillas e iteradores/rango, o como dijiste que el tamaño es fijo, una función que solo toma un puntero/ref de datos y codifica el tamaño (o si el tamaño puede variar, un adaptador de datos/tamaño como span)

    – subrayado_d

    11 de diciembre de 2018 a las 11:47


  • ¿por qué no simplemente anular foo (doble barra[ ])? si lo desea, también puede proporcionar la longitud de la matriz como void foo (doble barra[2]). A menos que para un tipo complejo se deba evitar un constructor de copias.

    – causa última

    5 de noviembre de 2019 a las 0:30


1646958669 183 C pasa una matriz por referencia
james kanze

Sí, pero cuando el argumento coincide con una referencia, la matriz implícita al puntero no es automática, por lo que necesita algo como:

void foo( double (&array)[42] );

o

void foo( double (&array)[] );

Tenga en cuenta, sin embargo, que al hacer coincidir, double [42] y double [] son tipos distintos. Si tiene una matriz de una dimensión desconocida, coincidirá con la segunda, pero no con la primera, y si tiene una matriz con 42 elementos, coincidirá con la primera. pero no el segundo. (Este último es, en mi humilde opinión, muy contrario a la intuición).

En el segundo caso, también tendrás que pasar la dimensión, ya que no hay forma de recuperarla una vez dentro de la función.

  • El segundo no compila para mí.

    – jrok

    4 de abril de 2012 a las 9:29

  • Para mi tampoco. No sé si se debe a un error del compilador o algo en el estándar que he pasado por alto. En realidad, nunca he querido hacerlo. (El primero es muy útil si la dimensión es un parámetro de plantilla, ya que el compilador determinará la dimensión correcta por usted).

    – James Kanze

    4 de abril de 2012 a las 9:37

  • No creo que el segundo ejemplo sea válido conforme al estándar C++. Por cierto, no se compila con GCC 4.8 o Clang 3.4. Creo que se requiere un tamaño de plantilla.

    – Ricky65

    18 mayo 2014 a las 12:13

  • @ Ricky65 Así es. Me pregunto porque. Las referencias a tipos incompletos normalmente se permiten como parámetros de función. (Por supuesto, en este caso, el tipo cambia cuando se completa: double [] y double [42] son dos tipos diferentes. Entonces, lo único que podría pasar a la última forma sería una matriz de longitud desconocida, por ejemplo extern double d[];, o algo así. Lo que limita seriamente la usabilidad.)

    – James Kanze

    19 de mayo de 2014 a las 8:24

1646958670 440 C pasa una matriz por referencia
moooeeeeep

Como está usando C ++, la sugerencia obligatoria que aún falta aquí es usar std::vector<double>.

Puedes pasarlo fácilmente por referencia:

void foo(std::vector<double>& bar) {}

Y si tiene soporte para C++ 11, también eche un vistazo a std::array.

Para referencia:

  • 🙂 Sí. std::vector suele ser la mejor solución. Pero hay excepciones.

    – James Kanze

    4 de abril de 2012 a las 9:28

C pasa una matriz por referencia
Naszta

Si desea modificar solo los elementos:

void foo(double *bar);

es suficiente.

Si desea modificar la dirección a (por ejemplo: realloc), pero no funciona para matrices:

void foo(double *&bar);

es la forma correcta.

8.3.5.8 Si el tipo de un parámetro incluye un tipo de la forma “puntero a matriz de límite desconocido de T” o “referencia a matriz de límite desconocido de T”, el programa está mal formado

1646958671 546 C pasa una matriz por referencia
parkovski

Como dice la otra respuesta, pon el & después de la *.

Esto trae a colación un punto interesante que a veces puede resultar confuso: los tipos deben leerse de derecha a izquierda. Por ejemplo, esto es (comenzando desde el extremo derecho *) un puntero a una constante puntero a un int.

int * const *x;

Por lo tanto, lo que escribió sería un puntero a una referencia, lo cual no es posible.

1646958671 882 C pasa una matriz por referencia
sergio06

Aquí, Erik explica todos los sentidos. pasar una matriz por referencia: https://stackoverflow.com/a/5724184/5090928.

Del mismo modo, puede crear un variable de referencia de matriz al igual que:

int arr1[] = {1, 2, 3, 4, 5};
int(&arr2)[5] = arr1;

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad