# Punteros C++
Un puntero es una variable. Pero no guarda un valor concreto. Guarda la direccion de memoria donde se encuentra otro valor (el valor "apuntado")
```
string saludo = "hola";
string* p;
p = &saludo;
*p = "amo programar";
```
El tamaño de un puntero es fijo y depende del compilador
## Variables de entorno y argumentos de linea de comando
### Stack
Variables automaticas(locales a las funciones).Crece hacia direcciones más bajas.
### Heap
Variables dinámicas.Crece hacia direcciones más altas
### BSS
variables no inicializadas
### Data
variables globales inicializadas
### Text
Instrucciones en codigo de máquina
## Stack
Cuando se inicia el programa se asigna una cantidad de espacio para la stack y no se modifica
Es donde se almacenan los datos de las funciones cuando se invocan
El tiempo de vida de las variables esta definido por el tiempo de vida de la funcion. Cuando la funcion termina. Las variables se eliminan automaticamente de la memoria
Los datos se apilan unos detras de otros. En una estructura de tipo (LIFO)
## Heap
EL espacio de memoria no es fijo. solo ocupa la porcion de memoria que necesita. Si necesita más va cogiendolo
Los datos se apilan de forma aleatoria (donde halla lugar). A esto se le llama fracmentacion.
Es más costoso alocar y desalocar espacio en ella.
La gestion de memoria es manual. Las variables tienen vida independiente de la funcion.
## ¿Pero la clase no era de punteros?
Las variables de la Heap no tienen un identificador. Para acceder a ella utilizamos los punteros.
Cuando utilizamos la instruccion `new` creamos una variable en heap ejemplo `int* x = new int;`
```
int* x = new int;
*x = 32;
```
es lo mismo que
`int x = new int(32);`
para eliminar esta variable usamos la palabra reservada delete
`delete x;`
elimina el dato apuntado y no el puntero.
Si tenemos dos punteros apuntando al mismo lugar y usamos delete ambos punteros quedan apuntando a un espacio de memoria "no valido"
ejemplo:
```
#include <iostream>
using namespace std;
int main(){
int* z = new int(5);
int* x = z;
delete z; //x queda como "danling pointer"
cout<<*x<<endl;
return 0
}
```
Tambien si necesito saber que el puntero no apunta a nada puedo usar el valor nullptr
```
int* z = nullptr;
```
* Todos los punteros ocupan lo mismo independientemente del dato al que apunte
* Tienen aritmetica de punteros
* Tienen varios niveles de indireccion
Puede haber más de un puntero apuntando a la misma dirección
```
int a=55;
int& b=a;
b=7;
```
## Referencias
c++ utiliza el mismo simbolo (**&**) para dos operaciones distintas. Declarar por referencia y para obtener la direccion de memoria de una variable
* Las referencias no pueden tener valor nulo y no pueden cambiar.
* Las referencias no tienen aritmetica de punteros
* generalmente usamos la referencia cuando se trabaja con datos grandes. Para no crear una copia de todo el dato.
* solo tienen un nivel de indireccion
**Los arreglos se pasan automaticamente por referencia
**
Desde la version 11 de c++ aparecen los **smartpointers** ejecutan delete cuando no hay un puntero a ese dato
[Visor de Stack y Heap](https://pythontutor.com/render.html#mode=display)
## Punteros
* Son un tipo especial de variable, que contiene una direccion de memoria ("apunta a un valor") en lugar de un valor concreto.
* Al declarar a un puntero, se debe indicar a qué tipo de dato apuntará.
* Los punteros son variables. Entonces, ellos también tienen su propia dirección de memoria.
* Para reservar memoria heap se utiliza el operador new
* La desreferencia es la operacion usada para acceder al valor guardado en la direccion de memoria apuntada Operador *
* El valor apuntado puede estar en la memoria stack o en la heap. Los punteros también pueden estar en ambas.