|
En clase ya conocimos algunos tipos básicos como por ejemplo los tipos char, int y float. El lenguaje C++ permite, además, construir estructuras más complejas a partir de estos tipos básicos.
Una de las construcciones que podemos definir son los arreglos.
Arreglo: Colección ordenada de elementos de un mismo tipo. Ordenada significa que cada elemento tiene una ubicación determinada dentro del arreglo y debemos conocerla para accederlo.
<tipo> nombre_variable[longitud];
Con esto diremos que nombre_variable es un arreglo de longitud elementos del tipo <tipo>. Cabe destacar que longitud debe ser cualquier expresión entera constante mayor que cero.
nombre_variable[índice] = expresión del tipo <tipo>
Esta instrucción asigna el valor asociado de la expresión a la posición índice del arreglo nombre_variable. El índice debe ser una expresión del tipo entero en el rango [0, longitud-1]. Cabe destacar que C++ no chequea que el valor de la expresión sea menor a longitud, simplemente asigna el valor a esa posición de memoria como si formara parte del arreglo, pisando, de esta manera, otros datos que no forman parte del mismo, con lo que finalmente el programa no funciona correctamente.
nombre_variable[índice] es valor del tipo <tipo> que puede ser asignado a una variable, o pasado como parámetro, imprimirlo, etc. Aquí también vale la aclaración de que el índice debe estar dentro del rango de definición del arreglo, C++ no chequeará que esto sea cierto y devolverá lo contenido en la posición de memoria correspondiente a un arreglo de mayor longitud, el dato obtenido de esta manera es basura.
int a[5]; // Definición de un arreglo de 5 posiciones
void main()
{
int i;
// Pedimos el ingreso de 5 números
for(i=0; i<4; i++) //No olvidar que los arreglos van de 0 a longitud-1
{
cout << Ingrese el elemento Nro: << i <<endl;
cin >> a[i];
}
// Los imprimimos
imprimir(a,5);
}
void imprimir(int b[], int tamano)
{
int i;
for(i=0; i<tamano; i++)
{
cout << Nro: << i <<" "<<b[i]<<endl;
}
}
Notar que el parámetro b de la función imprimir es un arreglo, pero no se indica la longitud del mismo. Esto no es necesario ya que solo especificamos que recibiremos un arreglo sin importar su longitud (en este caso particular su longitud viene indicada en tamano). De esta manera la función imprimir funciona para arreglos de cualquier longitud.
En Gofer tenemos como tipo básico al tipo lista. Este también tipo agrupa de forma ordenada elementos de un mismo tipo, pero existen varias diferencias importantes. Los arreglos en C++ son estáticos, es decir una vez definido su tamaño, este no crece ni decrece. Las listas de Gofer son dinámicas ya que su tamaño puede variar indefinidamente. En Gofer cuando agregamos un elemento a la lista obtenemos una nueva lista con todos los elementos corridos a la posición siguiente, en los arreglos solo asignamos valores a sus posiciones y cada uno de estos quedan en su posición, una asignación en la posición i no afecta a otra posición j si i es distinto de j.
En Gofer cuando pasamos parámetros a las funciones lo único que podemos hacer es operar con ellos para generar el resultado de la función, estos parámetros no se ven afectados ya que simplemente son expresiones del tipo de la aridad de la función.
En C++ existen diferentes posibilidades en el pasaje de parámetros, ya que estos pueden ser pasados por Valor o Copia o por Referencia, y cada uno tiene características diferentes.
Al declarar un parámetro por Valor, cuando la función es invocada, el valor del parámetro es copiado al entorno de la función, creando una nueva variable en el mismo. De esta forma la variable puede ser operada (cambiada) sin que esto afecte el valor de la variable en el entorno de la función llamadora. Este es el procedimiento que se asemeja al funcionamiento en Gofer.
De una manera gráfica, quizás se entienda mejor la idea:
Función llamadora Función llamada
Al declarar un parámetro por Referencia, cuando la función es invocada, el parámetro es referenciado por la variable de la función. De esta forma cada vez que utilizamos la variable declarada en realidad estamos utilizando la variable de la función llamadora. Esta forma de pasaje de parámetros abre una nueva posibilidad de comunicación entre funciones (se puede devolver resultados no solo como el resultado de la función), pero debe ser utilizada con cuidado, ya que es muy fácil introducir errores en el programa.
Función llamadora Función llamada
El parámetro es una referencia a la variable de la función llamadora, pero esta variable no puede ser modificada. De esta manera se logra un efecto similar al pasaje por Valor pero sin necesidad de hacer una copia. La razón de utilizar este tipo de pasaje de parámetros es la eficiencia, es más eficiente referenciar una variable que copiarla, siempre y cuando la variable sea de un tamaño considerable, por ejemplo no tiene sentido utilizar este tipo de pasaje de parámetros para enteros, pero sí para un arreglo de una gran dimensión. Con respecto a esto, cuando se declara una arreglo como parámetro de una función, aunque uno no aclare en el código, el arreglo es pasado por referencia (como en el ejemplo de la función imprimir un poco más arriba).
Tenemos el siguiente programa:
void main()
{
float a = 10, b = 20, c ;
cout << a << b ;
c = suma(a,b)
cout << "A+B= " << c;
cout <<" A es "<< a;
}
Caso 1) Pasaje por Valor o Copia
float suma(float a, float b)
{
a = a + b;
return (a);
}
Veamos que sucede cuando ejecutamos el programa:
float a = 10, b = 20, c ;
a = 10 b = 20 c = ¿?
c = suma(a,b) Entramos a suma
a = 10 b = 20 c = ¿?
asuma = 10 bsuma = 20
a = a + b;
a = 10 b = 20 c = ¿?
asuma = 30 bsuma = 20
return (a); Desaparecen asuma y bsuma
a = 10 b = 20 c = 30
Como vemos en este caso los parámetros no se ven afectados ya que suma realiza copias de a y b
Caso 2) Pasaje por Referencia
Cambiemos la declaración de suma declarando a a como referencia
float suma(float & a, float b)
Veamos que sucede cuando ejecutamos el programa:
float a = 10, b = 20, c ;
a = 10 b = 20 c = ¿?
c = suma(a,b) Entramos a suma
a = 10 b = 20 c = ¿?
asuma = aref bsuma = 20
a = a + b;
a = 30 b = 20 c = ¿?
asuma = aref bsuma = 20
return (a); Desaparecen asuma y bsuma
a = 30 b = 20 c = 30
Como vemos en este caso el parámetro a se ve afectado ya que suma utiliza una referencia a a
Caso 2) Pasaje por Referencia Constante
Cambiemos la declaración de suma declarando a a como referencia constante
float suma(const float & a, float b)
En este caso el compilador devolverá un error en la línea
a = a + b;
ya que se esta intentando modificar una referencia constante.
Aún no hay comentarios para este recurso.
Monografias, Exámenes, Universidades, Terciarios, Carreras, Cursos, Donde Estudiar, Que Estudiar y más: Desde 1999 brindamos a los estudiantes y docentes un lugar para publicar contenido educativo y nutrirse del conocimiento.
Contacto »