repos/CB100

Notas, resueltos y tps de la materia Algoritmos y Estructuras de Datos
Commits Files Refs README
notas/clases/teorica06.md (118 lines)

Clase 17-04-24

Templates

Los templates (o plantillas) sirven para definir funciones que no dependan de un tipo de dato, paro que su funcionamiento es el mismo para diferentes tipos. Por ejemplo la función swap que se muestra a continuación.

void swap(int& a, int&b) {
    int tmp = a;
    a = b;
    b = a;
}
void swap(float& a, float&b) {
    float tmp = a;
    a = b;
    b = a;
}

Sintaxis

Para definir una nueva Template, se utiliza la palabra reservada template seguido del nombre para referenciar al tipo entre signos < y >, antepuesto de la palabra reservada typename o class. Se recomienda utilizar typename en lugar de class ya que es más genérico.

template <typename Type>
void swap(Type& a, Type& b) {
    Type tmp = a;
    a = b;
    b = tmp;
}

Cuando se utiliza Templates en una clase la cual está modularizada en dos archivos, .h y .cpp por ejemplo, solo se puede utilizar template en la cabecera de la misma, en el ejemplo es el archivo .h, ya que en caso contrario se produce un error durante el enlace de los orchivos objeto (link) a la hora de compilar el programa

Punteros genéricos

Los punteros genéricos son punteros los cuales no tienen un tipo de dato asignado. Todos los punteros a diferentes tipos de datos ocupan la misma cantidad de memoria, un Word.

void *generic_pointer;

La ventaja de los punteros genéricos es que se puede usar un mismo puntero para manipular diferentes tipos de datos, la desventaja es que para acceder al dato apuntado por el puntero es necesario conocer el tamaño del tipo de dato al cual apunta el puntero, ya que si se desreferencia un puntero genérico se produce un error grave en el programa.

No se puede desreferencia un puntero genérico a menos que se conozca el tipo de dato

int a = 1;
void *p = &a;

std::cout << *(int *)p << std::endl; // "cast" al puntero `p` a tipo int para
                                     // acceder a la memoria que apunta

Memoria Dinámica

A diferencia de la memoria estática, que se localiza en el stack, la memoria dinámica se localiza en el heap. Al finalizar el programa el stack vuelve a su posición de origen y se eliminan todas las variables almacenadas allí, liberando la memoria utilizada, el heap en cambio, se debe liberar por el usuario antes de finalizado el programa, de lo contrario se produce una fuga de memoria, un error típico y grave en lenguajes como C y C++.

El lenguaje C++ ofrece dos palabra reservadas para manipular el heap: new la cual permite crear una nueva variable, y delete la cual permite eliminar una variable, y por consiguiente liberar la memoria utilizada por dicha variable

Sintaxis

La palabra new puede ser utilizada para almacenar memoria en el heap, la memoria a almacenar puede ser utilizada para variables de tipo primitivo como int, o variables más complejas como estructuras definidas por el usuario.

int *p = new int;
*p = 10;
std::cout << *p << std::endl;
delete p;

En el siguiente ejemplo se define un nuevo tipo de dato Vec2i, el cual representa un vector de dos elementos de tipo int. Luego, en la función main se utiliza el operador new para alocar la variable en el heap.

#include <iostream>

typedef struct {
    int x, y;
} Vec2i;

int main (void) {
    int *pos = new Vec2i;
    pos->x = 1;
    pos->y = 0;
    std::cout << "(" << p->x << "," << p->y << ")\n";
    delete Vec2i;
}
   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 ```