notas/clases/teorica06.md (3521B)
1 # Clase 17-04-24 2 3 ## Templates 4 5 Los templates (o plantillas) sirven para definir funciones que no dependan de un 6 tipo de dato, paro que su funcionamiento es el mismo para diferentes tipos. Por 7 ejemplo la función `swap` que se muestra a continuación. 8 9 ```c++ 10 void swap(int& a, int&b) { 11 int tmp = a; 12 a = b; 13 b = a; 14 } 15 ``` 16 17 ```c++ 18 void swap(float& a, float&b) { 19 float tmp = a; 20 a = b; 21 b = a; 22 } 23 ``` 24 25 ### Sintaxis 26 27 Para definir una nueva Template, se utiliza la palabra reservada `template` 28 seguido del nombre para referenciar al tipo entre signos `<` y `>`, antepuesto 29 de la palabra reservada `typename` o `class`. Se recomienda utilizar `typename` 30 en lugar de `class` ya que es más genérico. 31 32 ```c++ 33 template <typename Type> 34 void swap(Type& a, Type& b) { 35 Type tmp = a; 36 a = b; 37 b = tmp; 38 } 39 ``` 40 41 Cuando se utiliza Templates en una clase la cual está modularizada en dos 42 archivos, `.h` y `.cpp` por ejemplo, solo se puede utilizar `template` en la 43 cabecera de la misma, en el ejemplo es el archivo `.h`, ya que en caso 44 contrario se produce un error durante el enlace de los orchivos objeto (link) a 45 la hora de compilar el programa 46 47 ### Punteros genéricos 48 49 Los punteros genéricos son punteros los cuales no tienen un tipo de dato 50 asignado. Todos los punteros a diferentes tipos de datos ocupan la misma 51 cantidad de memoria, un **Word**. 52 53 ```c++ 54 void *generic_pointer; 55 ``` 56 57 La ventaja de los punteros genéricos es que se puede usar un mismo puntero para 58 manipular diferentes tipos de datos, la desventaja es que para acceder al dato 59 apuntado por el puntero es necesario conocer el tamaño del tipo de dato al cual 60 apunta el puntero, ya que si se desreferencia un puntero genérico se produce un 61 error **grave** en el programa. 62 63 > No se puede desreferencia un puntero genérico a menos que se conozca el tipo 64 > de dato 65 66 ```c++ 67 int a = 1; 68 void *p = &a; 69 70 std::cout << *(int *)p << std::endl; // "cast" al puntero `p` a tipo int para 71 // acceder a la memoria que apunta 72 ``` 73 74 ## Memoria Dinámica 75 76 A diferencia de la memoria estática, que se localiza en el **stack**, la memoria 77 dinámica se localiza en el **heap**. Al finalizar el programa el stack vuelve 78 a su posición de origen y se eliminan todas las variables almacenadas allí, 79 liberando la memoria utilizada, el heap en cambio, se debe liberar por el 80 usuario antes de finalizado el programa, de lo contrario se produce una fuga de 81 memoria, un error típico y grave en lenguajes como C y C++. 82 83 El lenguaje C++ ofrece dos palabra reservadas para manipular el heap: `new` la 84 cual permite crear una nueva variable, y `delete` la cual permite eliminar una 85 variable, y por consiguiente liberar la memoria utilizada por dicha variable 86 87 ### Sintaxis 88 89 La palabra `new` puede ser utilizada para almacenar memoria en el `heap`, la 90 memoria a almacenar puede ser utilizada para variables de tipo primitivo como 91 `int`, o variables más complejas como estructuras definidas por el usuario. 92 93 ```c++ 94 int *p = new int; 95 *p = 10; 96 std::cout << *p << std::endl; 97 delete p; 98 ``` 99 100 En el siguiente ejemplo se define un nuevo tipo de dato `Vec2i`, el cual 101 representa un vector de dos elementos de tipo `int`. Luego, en la función `main` 102 se utiliza el operador `new` para alocar la variable en el heap. 103 104 ```c++ 105 #include <iostream> 106 107 typedef struct { 108 int x, y; 109 } Vec2i; 110 111 int main (void) { 112 int *pos = new Vec2i; 113 pos->x = 1; 114 pos->y = 0; 115 std::cout << "(" << p->x << "," << p->y << ")\n"; 116 delete Vec2i; 117 } 118 ```
