2010-02-16 20 views
10

Mi profesor en C++ me dijo que la llamada por referencia solo debe usarse si no voy a cambiar nada en las matrices dentro de la función. Tengo algunos vectores muy grandes que estoy pasando en mi programa. Todos los vectores serán modificados dentro de las funciones. Mis matrices son de tamaños aproximadamente [256*256][256][50] ...pase por referencia C++

¿Hay alguna razón particular para no utilizar la referencia de llamada aquí?

¿La llamada AFAIK por referencia debe ser mucho más rápida y consumir menos memoria?

+3

Tal vez su maestro significa "pasar por ** la referencia const ** solo debe usarse si no va a cambiar ninguno de los datos dentro de la función ". – Dan

+0

No, no lo hizo. Nos dijo que es una regla práctica usar solo llamadas por referencia si no vas a cambiar nada. Veo ahora de las respuestas a continuación que incluso los maestros no siempre hablan de lo que están hablando. –

+0

Tienes razón. Los maestros no siempre saben de lo que están hablando. Y a veces lo saben, pero accidentalmente se equivocan. O a veces, dicen lo correcto, y los estudiantes los malinterpretan. No descarta la última opción. – jalf

Respuesta

5

Mi profesor en C++ me dijo que la llamada por referencia solo debería usarse si no voy a cambiar nada en las matrices dentro de la función.

Se debe utilizar cuando no va a cambiar algo dentro de la función o cambia las cosas y desea que los cambios se reflejarán en la matriz original o no se preocupan por los cambios se reflejen en la matriz original.

No debe usarse si no desea que cambie su matriz original (debe conservar los valores originales después de la llamada) y la función llamada cambia los valores del argumento pasado.

+1

Es absolutamente recomendable utilizarlo con arreglos más grandes, incluso si no quiere cambiarlo. En ese punto lo pasas por referencia constante y el compilador te mantendrá honesto. – Xorlev

+0

@Xorlev: Sí. ¿Dije algo más? Estoy leyendo mi respuesta, pero no puedo entender qué parte podría malinterpretarse. Está diciendo lo mismo. –

0

Por lo general, en los cursos introductorios, te dicen eso para que no cambies accidentalmente algo que no querías.

Como si pasaras en userName por referencia, y accidentalmente lo cambiaras a mrsbuxley que probablemente causaría errores, o por lo menos sería confuso más adelante.

4

Tu profesor está equivocado. Si necesita modificar matrices, pasar por referencia es el camino a seguir. Si no quiere algo modificado, pase por la referencia de referencia.

+2

En realidad, tal vez "incorrecto" es demasiado duro. Quizás "mal entendido" sea mejor. –

0

No veo ningún motivo por el que no pueda pasar por referencia. Alternativamente, podría pasar punteros, pero creo que pasar por referencia es mejor a veces, ya que evita las excepciones de puntero nulo.

Si su profesor lo ha sugerido como una especie de convención, no dude en romperlo si tiene sentido. Siempre puedes documentar esto en un comentario sobre la función.

1

Para evitar cambios accidentales, utilice pass-by-const-reference; de esa manera, por defecto *, la función llamada no puede cambiar la matriz pasada.

* Puede anularse con const_cast.

1

Puede pasar por referencia si:

  1. no modificará pasado objeto
  2. desea modificar objeto y no desea guardar objetos primitivos intactos

Cuando pase algo por referencia, luego solo se pasa el puntero a la función. Si pasa el objeto entero, entonces necesita copiarlo, por lo que consumirá más CPU y memoria.

1

Espera un segundo ... Tengo miedo de cómo las personas responden a esta.Las matrices, por lo que recuerdo, son siempre pasado por referencia.

void function(int array[]) 
{ 
    std::cout << array[0] << '\n'; 
} 

// somewhere else.. 
int array[2] = { 1, 2 }; 
function(array); // No copy happens here; it is passed by reference 

Además, usted no puede dice que el argumento de matriz es una referencia explícita, ya que sería la sintaxis para crear una serie de referencias (algo que no está permitido).

void function(int &array[]) // error here 
{ /* ... */ } 

¿A qué te refieres?

Además, muchos dicen que solo debe hacer eso si modifica los contenidos de la matriz dentro de la función. Entonces, ¿qué hay de referencia-a-const?

void function(const int arr[]) 
{ 
    std::cout << arr[0] << '\n'; 
} 

- editar

por favor que alguien me señale cómo no pasar una matriz por referencia en C++?

- edición

Oh, así que estamos hablando de vectores. De acuerdo, entonces las reglas generales son:

  • Pase por referencia solo cuando desee modificar el contenido del vector.
  • Pase por referencia-a-const siempre que pueda.
  • Pasar de valor solo cuando el objeto en cuestión es realmente, realmente pequeño (como una estructura que contiene un entero, por ejemplo), o cuando tiene sentido (no puedo pensar en un caso fuera de mi cabeza)

¿Echo de menos algo?

- edición

  • En el caso de las matrices C de fricción, que es una buena idea para pasarlos por referencia (como en void function(int (&array)[100])) cuando se quiere asegurar que la matriz tiene un tamaño definido dado.

Gracias, dribeas.

+0

esta confusión probablemente provenga de mi pregunta, ya que hablo de arreglos, pero en realidad me refiero a vectores ... –

+0

No se pasan por referencia, sino que se degradan en un puntero al primer elemento. El compilador cambiará la firma a 'void foo (int * array)' y las llamadas a 'foo (& array [0])'. Entonces otra vez ** puedes ** pasar una matriz por referencia: 'void foo (int (& array) [100])'. La sintaxis es un poco más oscura y el tamaño debe indicarse explícitamente (ya que es parte del tipo) pero puede hacerlo. –

1

En general, los objetos siempre se deben pasar por referencia. De lo contrario, se generará una copia del objeto y si el objeto es sustancialmente grande, esto afectará el rendimiento.

Ahora bien, si el método o función que está llamando no modificar el objeto, es una buena idea para declarar la función de la siguiente manera:

void some_function(const some_object& o); 

Esto generará un error de compilación si se intenta modificar el estado del objeto dentro del cuerpo de la función.

También se debe tener en cuenta que las matrices siempre se pasan por referencia.

8

Además de todas las discusiones comunes sobre cuándo y cómo pasar posiblemente por referencias para tipos no primitivos, las matrices son bastante especiales aquí.

Debido a la compatibilidad con C, y debido a su problema específico: las matrices pueden ser enormes, las matrices nunca pasan realmente el valor en C ni en C++. La matriz descomposición en un puntero al primer elemento, por lo que cuando se escribe:

void foo(type array[100]); 

el compilador está procesando realmente:

void foo(type *array); 

Independientemente de cuál sea el tamaño de la matriz es (dos Errores comunes allí: confiando en que array es una matriz dentro de foo y en la creencia de que se garantizará que sean 100 elementos en ella.

Ahora, en C++ puede pasar las matrices por referencia E, pero la referencia debe ser del tipo concreto de la matriz, que incluye el tamaño:

void foo_array(type (&array)[100]); 

La sintaxis divertido no está diciendo al compilador que la función se llevará a una serie de exactamente 100 elementos de tipo type. La ventaja no es que el compilador puede realizar tamaño comprobación de que:

// assuming 'type' is defined 
int main() { 
    type array0[99]; 
    type array1[100]; 

    foo(array0);  // compiles, but if size=100 is assumed it will probably break 
         // equivalent to: foo(&array0[0]) 
    // foo2(array0); // will not compile, size is not 100 
    foo2(array1); // compiles, size is guaranteed to be 100 
} 

Ahora, el problema es que su función sólo funcionará para una serie de exactamente 100 elementos, y en algunos casos, es posible que desee realizar la misma operación en diferentes tamaños de matriz. Las dos soluciones son: plantilla la función en el tamaño de la matriz que proporcionará una implementación de tamaño seguro para cada tamaño utilizado - mayor tiempo de compilación y tamaño binario, la plantilla se compila para cada tamaño diferente-- o utilizando el pase la sintaxis de valor por valor, que hará que la matriz decaiga, no es segura en tamaño, debe pasar como argumento adicional, menor tiempo de compilación y tamaño binario. Una tercera opción es la combinación de ambos:

void foo(type *array, int size); 
template <size_t N> 
void foo(type (&array)[N]) { 
    foo(array, N); 
} 

En este caso, mientras que habrá una plantilla foo para cada tamaño, el compilador lo más probable es inline la llamada y el código generado sería equivalente a la persona que llama que proporciona la matriz y tamaño No se necesitan cálculos adicionales y tipo de seguridad para matrices reales.

Ahora, el paso por referencia se utiliza muy raramente con las matrices.

+1

Respuesta muy, muy útil, al menos para mí. Siempre me pregunté cómo crear arreglos de tamaño seguro así. ¡Guay! (+1, obviamente) –

0

Nuestro estilo de casa es NUNCA pasar un objeto por valor pero siempre pasar una referencia o referencia constante. No solo tenemos estructuras de datos que pueden contener cientos de MB de datos y pasar por valor sería un asesino de aplicaciones, sino que también, si aprobamos puntos tridimensionales y vectores por valor, nuestras aplicaciones se detendrían.

0

Siempre es una buena opción pasar el objeto por referencia, pero tenemos que tener cuidado y primero tenemos que decidir cuál es nuestro propósito/propósito de nuestra función.

Tiene que hacer una elección aquí, ya sea que solo leamos los datos de un objeto o lo modifiquemos.

Supongamos que tienes una interfaz como

void increament_value(int& a); 

lo que en este se puede modificar el valor de un objeto que estamos pasando, pero es un desastre cuando pasa sus datos sensibles, es posible que se pierdan datos originales y no puede revertirlo, ¿verdad?

modo C++ que proporciona una funcionalidad para no cambiar el valor de un objeto cuya referencia está de paso a una función, y siempre es una buena opción para pasar una referencia const de un objeto para, por ejemplo,

double get_discounted_amount(const double &amount,double discount){ 
    return (amount*discount/100); 
} 

Esto garantiza que el valor real de un objeto no va a cambiar, pero de nuevo depende del propósito de su interfaz si usted quiere cambiar o sólo el uso (leer) que

Cuestiones relacionadas