fundamentos de la programación 2013 2014 9 · al copiarle otro puntero (con el mismo tipo base)...

47
13/05/2014 1 9 Grado en Ingeniería Informática Grado en Ingeniería del Software Grado en Ingeniería de Computadores Luis Hernández Yáñez Facultad de Informática Universidad Complutense Fundamentos de la programación 20132014 Luis Hernández Yáñez Página 1 Fundamentos de la programación: Punteros y memoria dinámica Direcciones de memoria y punteros 2 Operadores de punteros 7 Punteros y direcciones válidas 17 Punteros no inicializados 19 Un valor seguro: NULL 20 Copia y comparación de punteros 21 Tipos de punteros 26 Punteros a estructuras 28 Punteros a constantes y punteros constantes 30 Punteros y paso de parámetros 32 Punteros y arrays 36 Memoria y datos del programa 39 Memoria dinámica 44 Punteros y datos dinámicos 48 Gestión de la memoria 61 Inicialización de datos dinámicos 64 Errores comunes 66 Arrays de datos dinámicos 71 Arrays dinámicos 83

Upload: others

Post on 31-Jul-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

1

9

GradoenIngenieríaInformáticaGradoenIngenieríadelSoftware

GradoenIngenieríadeComputadores

LuisHernándezYáñez

FacultaddeInformáticaUniversidadComplutense

Fundamentos de la programación  2013‐2014

Luis Hernández Yáñez

Página 1Fundamentos de la programación: Punteros y memoria dinámica

Direcciones de memoria y punteros 2Operadores de punteros 7Punteros y direcciones válidas 17

Punteros no inicializados 19Un valor seguro: NULL 20

Copia y comparación de punteros 21Tipos de punteros 26

Punteros a estructuras 28Punteros a constantes y punteros constantes 30

Punteros y paso de parámetros 32Punteros y arrays 36Memoria y datos del programa 39Memoria dinámica 44Punteros y datos dinámicos 48Gestión de la memoria 61

Inicialización de datos dinámicos 64Errores comunes 66Arrays de datos dinámicos 71Arrays dinámicos 83

Page 2: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

2

Luis Hernández Yáñez

Página 2Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

LosdatosenlamemoriaTododato(variableoconstante)deunprogramasealmacenaenlamemoria:enunoscuantosbytesapartirdeunadirección.

int i = 5;

Eldato(i)seaccedeapartirdesudirecciónbase (0F03:1A38),ladireccióndelaprimeraceldadememoriautilizadaporesedato.Eltipodeldato(int)indicacuántasceldas(bytes)utilizaesedato(4):00000000 00000000 00000000 00000101  5(Lacodificacióndelosdatospuedeserdiferente.Yladelasdireccionestambién.)

Página 3Fundamentos de la programación: Punteros y memoria dinámica

0F03:1A37 ...

i 0F03:1A38 00000000

0F03:1A39 00000000

0F03:1A3A 00000000

0F03:1A3B 00000101

0F03:1A3C ...

5DirecciónbaseDirecciónbase

Page 3: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

3

Luis Hernández Yáñez

LospunteroscontienendireccionesdememoriaUnavariablepuntero (osimplementepuntero)sirveparaaccederatravésdeellaaotrodatodelprograma.

Elvalordelpunteroseráladireccióndememoriabasedeotrodato.

Página 4Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38 00

0F03:1A39 00

0F03:1A3A 00

0F03:1A3B 05

...

punt 0F07:0417 0F

0F07:0418 03

0F07:0419 1A

0F07:041A 38

...

¿Dequétipoeseldatoapuntado?¿Cuántasceldasocupa?¿Cómoseinterpretanlos0sy1s?

¿Dequétipoeseldatoapuntado?¿Cuántasceldasocupa?¿Cómoseinterpretanlos0sy1s?

Indirección:AccesoindirectoaundatoIndirección:Accesoindirectoaundato

puntpunt

5ii

punt apunta aipunt apunta ai

Luis Hernández Yáñez

Lospunteroscontienendireccionesdememoria¿Dequétipoeseldatoapuntado?

Lavariablealaqueapuntaunpuntero,comocualquierotravariable,serádeuntipoconcreto(¿cuántoocupa?¿cómoseinterpreta?).

Eltipodevariablealaqueapuntaunpunteroseestablecealdeclararlavariablepuntero:

tipo *nombre;

Elpunteronombre apuntaráaunavariabledeltipo indicado(eltipobasedelpuntero).

Elasterisco(*)indicaqueesunpunteroadatosdeesetipo.int *punt; // punt inicialmente contiene una dirección

// que no es válida (no apunta a nada).

Elpunteropunt apuntaráaunavariableentera(int).int i; // Dato entero  vs. int *punt; // Puntero a entero

Página 5Fundamentos de la programación: Punteros y memoria dinámica

Page 4: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

4

Luis Hernández Yáñez

LospunteroscontienendireccionesdememoriaLasvariablespunterotampocoseinicializanautomáticamente.Aldeclararlassininicializadorcontienendireccionesquenosonválidas.int *punt; // punt inicialmente contiene una dirección

// que no es válida (no apunta a nada).

Unpunteropuedeapuntaracualquierdatodeltipobase.

Unpunteronotieneporquéapuntarnecesariamenteaundato(puedenoapuntaranada:valorNULL).

¿Paraquésirvenlospunteros?

Paraimplementarelpasodeparámetrosporreferencia.

Paramanejardatosdinámicos.(Datosquesecreanydestruyendurantelaejecución.)

Página 6Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Página 7Fundamentos de la programación: Punteros y memoria dinámica

Page 5: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

5

Luis Hernández Yáñez

Obtenerladireccióndememoriade...Eloperadormonario& devuelveladireccióndememoriabasedeldatoalqueseaplicaeloperador.Operadorprefijo(precede).int i;

cout << &i; // Muestra la dirección de memoria de i

Aunpunteroselepuedeasignarladirecciónbasedecualquierdatodelmismotipoqueeltipobasedelpuntero:int i;

int *punt;

punt = &i; // punt contiene la dirección base de i

Ahora,elpunteropunt yacontieneunadireccióndememoriaválida.

punt apunta a(contieneladirecciónbasede)lavariableenterai (int).

Página 8Fundamentos de la programación: Punteros y memoria dinámica

&&

puntpunt

5ii

Luis Hernández Yáñez

Obtenerladireccióndememoriade...

int i, j;

...

int *punt;

Página 9Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38

0F03:1A39

0F03:1A3A

0F03:1A3B

j 0F03:1A3C

0F03:1A3D

0F03:1A3E

0F03:1A3F

...

punt 0F07:0417

0F07:0418

0F07:0419

0F07:041A

...

&&

Page 6: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

6

Luis Hernández Yáñez

Obtenerladireccióndememoriade...

int i, j;

...

int *punt;

...

i = 5;

Página 10Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38 00

0F03:1A39 00

0F03:1A3A 00

0F03:1A3B 05

j 0F03:1A3C

0F03:1A3D

0F03:1A3E

0F03:1A3F

...

punt 0F07:0417

0F07:0418

0F07:0419

0F07:041A

...

&&

5ii

Luis Hernández Yáñez

Obtenerladireccióndememoriade...

int i, j;

...

int *punt;

...

i = 5;

punt = &i;

Página 11Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38 00

0F03:1A39 00

0F03:1A3A 00

0F03:1A3B 05

j 0F03:1A3C

0F03:1A3D

0F03:1A3E

0F03:1A3F

...

punt 0F07:0417 0F

0F07:0418 03

0F07:0419 1A

0F07:041A 38

...

&&

puntpunt

5ii

Page 7: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

7

Luis Hernández Yáñez

Obtenerloquehayenladirección...Eloperadormonario* accedealoquehayenladireccióndememoriaalaqueseaplicaeloperador(unpuntero).Operadorprefijo(precede).

Unavezqueunpunterocontieneunadireccióndememoriaválida,sepuedeaccederaldatoalqueapuntaconesteoperador.punt = &i;

cout << *punt; // Muestra lo que hay en la dirección punt

*punt:loquehayenladirecciónquecontieneelpunteropunt.

Comoelpunteropunt contieneladireccióndememoriadelavariablei,*punt accedealcontenidodeesavariablei.

Accesoindirectoalvalordei.

Seobtienen,apartirdeladireccióndememoriabasequecontienepunt,tantosbytescomocorrespondanaltipobase(int)(4)yseinterpretancomoundatodeesetipobase(int).

Página 12Fundamentos de la programación: Punteros y memoria dinámica

**Luis Hernández Yáñez

Obtenerladireccióndememoriade...

int i, j;

...

int *punt;

...

i = 5;

punt = &i;

j = *punt;

Página 13Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38 00

0F03:1A39 00

0F03:1A3A 00

0F03:1A3B 05

j 0F03:1A3C

0F03:1A3D

0F03:1A3E

0F03:1A3F

...

punt 0F07:0417 0F

0F07:0418 03

0F07:0419 1A

0F07:041A 38

...

0F0F

0303

1A1A

3838punt:punt:

**

Page 8: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

8

Luis Hernández Yáñez

Obtenerladireccióndememoriade...

int i, j;

...

int *punt;

...

i = 5;

punt = &i;

j = *punt;

Página 14Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38 00

0F03:1A39 00

0F03:1A3A 00

0F03:1A3B 05

j 0F03:1A3C

0F03:1A3D

0F03:1A3E

0F03:1A3F

...

punt 0F07:0417 0F

0F07:0418 03

0F07:0419 1A

0F07:041A 38

...

0000

0000

0000

0505

*punt:*punt:

**

Direccionamientoindirecto 

(indirección). Se accede al dato ide forma indirecta.

Direccionamientoindirecto 

(indirección). Se accede al dato ide forma indirecta.

Luis Hernández Yáñez

Obtenerladireccióndememoriade...

int i, j;

...

int *punt;

...

i = 5;

punt = &i;

j = *punt;

Página 15Fundamentos de la programación: Punteros y memoria dinámica

...

i 0F03:1A38 00

0F03:1A39 00

0F03:1A3A 00

0F03:1A3B 05

j 0F03:1A3C

0F03:1A3D

0F03:1A3E

0F03:1A3F

...

punt 0F07:0417 0F

0F07:0418 03

0F07:0419 1A

0F07:041A 38

...

0000

0000

0000

0505

**

Page 9: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

9

Luis Hernández Yáñez

Ejemplodeusodepunteros#include <iostream>using namespace std;

int main() {int i = 5;int j = 13;int *punt;punt = &i;cout << *punt << endl; // Muestra el valor de ipunt = &j;cout << *punt << endl; // Ahora muestra el valor de jint *otro = &i;cout << *otro + *punt << endl; // i + jint k = *punt;cout << k << endl; // Mismo valor que j

return 0;}

Página 16Fundamentos de la programación: Punteros y memoria dinámica

punteros.cpp

Luis Hernández Yáñez

Página 17Fundamentos de la programación: Punteros y memoria dinámica

Page 10: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

10

Luis Hernández Yáñez

TodopunterohadetenerunadirecciónválidaUnpunterosólodebeserutilizadoparaaccederaldatoalqueapunte,siseestásegurodequecontieneunadirecciónválida.

UnpunteroNOcontieneunadirecciónválidatrasserdefinido.

Unpunteroobtieneunadirecciónválida:

Alcopiarleotropuntero(conelmismotipobase)queyacontengaunadirecciónválida.

Alasignarleladireccióndeotrodatoconeloperador&.

AlasignarleelvalorNULL (indicaquesetratadeunpunteronulo,unpunteroquenoapuntaanada).

int i;int *q; // q no tiene aún una dirección válidaint *p = &i; // p toma una dirección válidaq = NULL; // ahora q ya tiene una dirección válidaq = p; // otra dirección válida para q

Página 18Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Punterosqueapuntanasaberqué...Unapunteronoinicializadocontieneunadireccióndesconocida.int *punt; // no inicializado*punt = 12;

¿Direccióndelazonadedatosdelprograma?¡Podemosestarmodificandoinadvertidamenteundatodelprograma! Elprogramanoobtendríalosresultadosesperados.

¿Direccióndelazonadecódigodelprograma?¡Podemosestarmodificandoelpropiocódigodelprograma! Sepodríaejecutarunainstrucciónincorrecta ???

¿Direccióndelazonadecódigodelsistemaoperativo?¡PodemosestarmodificandoelcódigodelpropioS.O.! Consecuenciasimprevisibles(cuelgue)

Página 19Fundamentos de la programación: Punteros y memoria dinámica

Page 11: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

11

Luis Hernández Yáñez

PunterosquenoapuntananadaInicializandolospunterosaNULL podemosdetectarerrores:int *punt = NULL;...*punt = 13;

punt hasidoinicializadoaNULL:¡Noapuntaanada!

Sinoapuntaanada,¿¿¿quésignifica*punt???Notienesentido.

ERROR:¡Seintentaaccederaundatoatravésdeunpunteronulo!

Seproduceunerrordeejecución,loqueciertamentenoesbueno.

Perosabemosexactamentecuálhasidoelproblema,loqueesmucho.

Sabemospordóndeempezarainvestigar(depurar)yquébuscar.

Página 20Fundamentos de la programación: Punteros y memoria dinámica

Xpuntpunt

Luis Hernández Yáñez

Página 21Fundamentos de la programación: Punteros y memoria dinámica

Page 12: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

12

Luis Hernández Yáñez

ApuntandoalmismodatoCuandocopiamosunpunterosobreotro,ambosapuntanalmismodato:

int x = 5;int *punt1 = NULL; // punt1 no apunta a nadaint *punt2 = &x; // punt2 apunta a la variable x

Página 22Fundamentos de la programación: Punteros y memoria dinámica

Xpunt1punt1 punt2punt2

5xx

Luis Hernández Yáñez

ApuntandoalmismodatoCuandocopiamosunpunterosobreotro,ambosapuntanalmismodato:

int x = 5;int *punt1 = NULL; // punt1 no apunta a nadaint *punt2 = &x; // punt2 apunta a la variable xpunt1 = punt2; // ambos apuntan a la variable x

Página 23Fundamentos de la programación: Punteros y memoria dinámica

punt1punt1 punt2punt2

5xx

Page 13: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

13

Luis Hernández Yáñez

ApuntandoalmismodatoCuandocopiamosunpunterosobreotro,ambosapuntanalmismodato:

int x = 5;int *punt1 = NULL; // punt1 no apunta a nadaint *punt2 = &x; // punt2 apunta a la variable xpunt1 = punt2; // ambos apuntan a la variable x*punt1 = 8;

Página 24Fundamentos de la programación: Punteros y memoria dinámica

punt1punt1 punt2punt2

8xx

Alavariablexahorasepuedeaccederde3formas:

x  *punt1  *punt2

Alavariablexahorasepuedeaccederde3formas:

x  *punt1  *punt2

Luis Hernández Yáñez

¿Apuntanalmismodato?Losoperadoresrelacionales== y!= nospermitensabersidospunterosapuntanaunmismodato:

int x = 5;int *punt1 = NULL;int *punt2 = &x;...if (punt1 == punt2)

cout << "Apuntan al mismo dato" << endl;else

cout << "No apuntan al mismo dato" << endl;

Sólotienesentidocompararpunterosconelmismotipobase.

Página 25Fundamentos de la programación: Punteros y memoria dinámica

Page 14: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

14

Luis Hernández Yáñez

Página 26Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

DeclaracióndetiposdepunterosDeclaramostiposparalospunteroscondistintostiposbase:typedef int *intPtr;typedef char *charPtr;typedef double *doublePtr;int entero = 5;intPtr puntI = &entero;char caracter = 'C';charPtr puntC = &caracter;double real = 5.23;doublePtr puntD = &real;cout << *puntI << "  " << *puntC << "  " << *puntD << endl;

Con*puntero podemoshacerloquesepuedahacerconlosdatosdeltipobasedelpuntero.

Página 27Fundamentos de la programación: Punteros y memoria dinámica

tipos.cpp

Page 15: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

15

Luis Hernández Yáñez

AccesoaestructurasatravésdepunterosLospunterospuedenapuntaracualquiertipodedatos,tambiénestructuras:typedef struct {

int codigo;string nombre;double sueldo;

} tRegistro;tRegistro registro;typedef tRegistro *tRegistroPtr;tRegistroPtr puntero = &registro;

Operadorflecha(‐>):Permiteaccederaloscamposdeunaestructuraatravésdeunpunterosineloperadordeindirección(*).

puntero‐>codigo puntero‐>nombre    puntero‐>sueldo

puntero‐>... (*puntero)....

Página 28Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Accesoaestructurasatravésdepunterostypedef struct {

int codigo;string nombre;double sueldo;

} tRegistro;tRegistro registro;typedef tRegistro *tRegistroPtr;tRegistroPtr puntero = &registro;registro.codigo = 12345;registro.nombre = "Javier";registro.sueldo = 95000;cout << puntero‐>codigo << "  " << puntero‐>nombre 

<< "  " << puntero‐>sueldo << endl;

puntero‐>codigo (*puntero).codigo *puntero.codigo

Página 29Fundamentos de la programación: Punteros y memoria dinámica

structPtr.cpp

Seesperaríaquepuntero fueraunestructuraconcampocodigo detipopuntero.Seesperaríaquepuntero fueraunestructuraconcampocodigo detipopuntero.

Page 16: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

16

Luis Hernández Yáñez

PunterosaconstantesypunterosconstantesCuandosedeclaranpunterosconelmodificadordeaccesoconst,suefectodependededóndesecoloqueenladeclaración:

const tipo *puntero; Punteroaunaconstante

tipo *const puntero; Punteroconstante

Punterosaconstantes:typedef const int *intCtePtr; // Puntero a dato constante

int entero1 = 5, entero2 = 13;

intCtePtr punt_a_cte = &entero1;

(*punt_a_cte)++; // ERROR: ¡Dato constante no modificable!

punt_a_cte = &entero2; // Sin problema: el puntero no es cte.

Página 30Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

PunterosaconstantesypunterosconstantesPunterosconstantes:typedef int *const intPtrCte; // Puntero constante

int entero1 = 5, entero2 = 13;

intPtrCte punt_cte = &entero1;

(*punt_cte)++; // Sin problema: el puntero no apunta a cte.

punt_cte = &entero2; // ERROR: ¡Puntero constante!

Página 31Fundamentos de la programación: Punteros y memoria dinámica

constPtr.cpp

Page 17: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

17

Luis Hernández Yáñez

Página 32Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

PasodeparámetrosporreferenciaovariableEnellenguajeCnoexisteelmecanismodepasodeparámetroporreferencia(&).Sólosepuedenpasarparámetrosporvalor.

¿Cómoseimplementaentonceselpasoporreferencia?

Pormediodepunteros:

void incrementa(int *punt);

void incrementa(int *punt) {(*punt)++;

}...int entero = 5;incrementa(&entero);cout << entero << endl;

Mostrará6 enlaconsola.

Página 33Fundamentos de la programación: Punteros y memoria dinámica

Pasoporvalor:

Elargumentonosemodificatraslaejecución

(elpuntero nocambia).

PeroaquelloaloqueapuntaSÍ(elentero semodificaatravésdepuntero).

Pasoporvalor:

Elargumentonosemodificatraslaejecución

(elpuntero nocambia).

PeroaquelloaloqueapuntaSÍ(elentero semodificaatravésdepuntero).

param.cpp

Page 18: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

18

Luis Hernández Yáñez

Pasodeparámetrosporreferenciaovariableint entero = 5;incrementa(&entero);

Página 34Fundamentos de la programación: Punteros y memoria dinámica

5enteroentero

puntpunt

6enteroentero

punt recibeladireccióndeenteropunt recibeladireccióndeentero

6enteroentero

void incrementa(int *punt) {(*punt)++;

}

cout << entero << endl;

Luis Hernández Yáñez

Pasodeparámetrosporreferenciaovariable¿Cuáleselequivalenteconpunterosaesteprototipo?¿Cómosellama?void foo(int &param1, double &param2, char &param3);

Prototipoequivalente:

void foo(int *param1, double *param2, char *param3);

void foo(int *param1, double *param2, char *param3) {// Al primer argumento se accede con *param1// Al segundo argumento se accede con *param2// Al tercer argumento se accede con *param3

}

Llamada:int entero; double real; char caracter;//...foo(&entero, &real, &caracter);

Página 35Fundamentos de la programación: Punteros y memoria dinámica

Page 19: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

19

Luis Hernández Yáñez

Página 36Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

UnaíntimarelaciónNombredevariablearray Punteroalprimerelementodelarray

Así,sitenemos:int dias[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

Entonces:cout << *dias << endl;

Muestra31 enlaconsola,elprimerelementodelarray.

¡Elnombredelarrayesunpunteroconstante!Siempreapuntaalprimerelemento.Nosepuedemodificarsudirección.

Alrestodeloselementosdelarray,ademásdeporíndice,selespuedeaccederpormediodelasoperacionesaritméticasdepunteros.

Página 37Fundamentos de la programación: Punteros y memoria dinámica

Page 20: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

20

Luis Hernández Yáñez

Pasodearraysafunciones¡Estoexplicaporquénousamos&conlosparámetrosarray!Comoelnombredelarrayesunpuntero,yaesunpasoporreferencia.Declaracionesalternativasparaparámetrosarray:const int N = ...;void cuadrado(int array[N]);void cuadrado(int array[], int size); // Array no delimitadovoid cuadrado(int *array, int size); // Puntero

Lastresdeclaracionesdelparámetroarraysonequivalentes.Arraysnodelimitados:Noindicamoseltamaño,pudiendoaceptarcualquierarraydeesetipobase(int).Conarraysnodelimitadosypunterossehadeproporcionarladimensiónparapoderrecorrerelarray.Independientementedecómosedeclareelparámetro,dentrosepuedeaccederaloselementosconíndice(array[i])oconpuntero(*array).

Página 38Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Página 39Fundamentos de la programación: Punteros y memoria dinámica

Page 21: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

21

Luis Hernández Yáñez

Página 40Fundamentos de la programación: Punteros y memoria dinámica

RegionesdelamemoriaElS.O.disponeenlamemoriadelacomputadoravariasregionesdondesealmacenandistintascategoríasdedatosdelprograma:

Pila (Stack)

Montón (Heap)

Datos globales

Código del programa

S.O.

DatoslocalesDatoslocales

DatosdinámicosDatosdinámicos

MemoriaprincipalMemoriaprincipal

Luis Hernández Yáñez

Página 41Fundamentos de la programación: Punteros y memoria dinámica

LamemoriaprincipalEnlamemoriaprincipal sealojanlosdatosglobalesdelprograma:losqueestándeclaradosfueradelasfunciones.typedef char tCadena[80];typedef struct {

...} tRegistro;cont int N = 1000;typedef tRegistro tLista[N];typedef struct {

tLista registros;int cont;

} tTabla;

int main() {...

Pila

Montón

Datos globales

Código del programa

S.O.

DatoslocalesDatoslocales

DatosdinámicosDatosdinámicos

MemoriaprincipalMemoriaprincipal

Page 22: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

22

Luis Hernández Yáñez

Página 42Fundamentos de la programación: Punteros y memoria dinámica

Lapila(stack)Enlapila delsistemaseguardanlosdatoslocales:parámetrosporvaloryvariableslocalesdelasfunciones.

void func(tTabla tabla, double &total){tTabla aux;int i;...

Tambiénseguardanlospunterosquesemanejaninternamenteparaapuntaralosargumentosdelosparámetrosporreferencia.

Pila

Montón

Datos globales

Código del programa

S.O.

DatoslocalesDatoslocales

DatosdinámicosDatosdinámicos

MemoriaprincipalMemoriaprincipal

func(tabla, resultado)

&resultado

Luis Hernández Yáñez

Página 43Fundamentos de la programación: Punteros y memoria dinámica

Elmontón(heap)Elmontón esunaenormezonadealmacenamientodondepodemosalojartemporalmentedatosdelprogramaquesecreenysedestruyanamedidaquesenecesitendurantelaejecucióndelprograma.

Datoscreadosdurantelaejecucióndelprograma:Datosdinámicos

Sistemadegestióndememoriadinámica(SGMD):

CuandosenecesitamemoriaparaunavariablesesolicitaéstaalSGMD,quienreservalacantidadadecuadaparaesetipodevariableydevuelveladireccióndelaprimeraceldadememoriadelazonareservada.

Cuandoyanosenecesitamáslavariable,seliberalamemoriaqueutilizabaindicandoalSGMDquepuedecontardenuevoconlamemoriaquesehabíareservadoanteriormente.

Pila

Montón

Datos globales

Código del programa

S.O.

DatoslocalesDatoslocales

DatosdinámicosDatosdinámicos

MemoriaprincipalMemoriaprincipal

Page 23: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

23

Luis Hernández Yáñez

Página 44Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Página 45Fundamentos de la programación: Punteros y memoria dinámica

DatosdinámicosDatosquesecreanysedestruyendurantelaejecucióndelprograma.Selesasignamemoriadelmontón.

¿Porquéutilizarlamemoriadinámica? Esunalmacéndememoriamuygrande:aquellosdatosolistasdedatosquenoquepanenmemoriaprincipal,oqueconsumandemasiadoespacioenlapila,puedenseralojadosenelmontón.

Elprogramaajustaelusodelamemoriaalasnecesidadesdecadamomento:nilefaltaniladesperdicia.

MontónDato dinámico

CreaciónCreación

DestrucciónDestrucción

Page 24: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

24

Luis Hernández Yáñez

Página 46Fundamentos de la programación: Punteros y memoria dinámica

¿Cuándoseasignamemoriaalosdatos?

Datosglobales:Secreanenlamemoriaprincipaldurantelacargadelprograma.Existendurantetodalaejecucióndelprograma.

Datoslocales deunafunción(incluyendoparámetros):Seguardanenlapiladelsistemadurantelaejecucióndeesafunción.Existensólodurantelaejecucióndeesafunción.

Datosdinámicos:Secreanenelmontón(heap)cuandoelprogramalossolicitaysedestruyencuandoelprogramaigualmentelosolicita.Existenavoluntad delprograma.

Luis Hernández Yáñez

Página 47Fundamentos de la programación: Punteros y memoria dinámica

Datosestáticos Constantesyvariablesdeclaradascomodeuntipoconcreto:int i;

Suinformaciónseaccededirectamenteatravésdelidentificador:cout << i;

Datosdinámicos Constantesyvariablesaccedidasatravésdesudireccióndememoria.

Senecesitatenerguardadaesadireccióndememoriaenalgúnsitio:Puntero.

Yahemosvistoquelosdatosestáticostambiénsepuedenaccederatravésdepunteros(int *p = &i;).

Page 25: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

25

Luis Hernández Yáñez

Página 48Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Página 49Fundamentos de la programación: Punteros y memoria dinámica

Operadores new y deleteHastaahorahemostrabajadoconpunterosquecontienendireccionesdedatosestáticos(variablesenmemoriaprincipaloenlapila).

Sinembargo,lospunterostambiénsonlabasesobrelaqueseapoyaelsistemadegestióndinámicadememoria.

Cuandoqueremoscrearunavariabledinámicadeuntipodeterminado,pedimosmemoriadelmontónconeloperadornew.

Eloperadornew reservalamemorianecesariaparaesetipodevariableydevuelveladireccióndelaprimeraceldadememoriaasignadaalavariable;esadirecciónseguardaenunpuntero.

Cuandoyanonecesitemoslavariable,devolvemoslamemoriaqueutilizaalmontónmedianteeloperadordelete.

Aloperadorselepasaunpunteroconladireccióndelaprimeraceldadememoria(delmontón)utilizadaporlavariable.

Page 26: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

26

Luis Hernández Yáñez

Página 50Fundamentos de la programación: Punteros y memoria dinámica

Eloperadornewnew tipo Reservamemoriadelmontónparaunavariablede

esetipo ydevuelvelaprimeradireccióndememoriautilizada,quedebeserasignadaaunpuntero.

int *p; // Todavía sin una dirección válidap = new int; // Ya tiene una dirección válida*p = 12;

Lavariabledinámicaseaccedeexclusivamenteatravésdepunteros;nohayningúnidentificadorasociadoconellaquepermitaaccederla.int i; // i es una variable estáticaint *p1, *p2;p1 = &i; // Puntero que da acceso a la variable

// estática i (accesible con i o con *p1)p2 = new int; // Puntero que da acceso a una variable

// dinámica (accesible sólo a través de *p2)

Luis Hernández Yáñez

Página 51Fundamentos de la programación: Punteros y memoria dinámica

Eloperadordeletedelete puntero; Devuelvealmontónlamemoriautilizadapor

lavariabledinámicaapuntadaporpuntero.int *p;p = new int;*p = 12;...delete p; // Ya no se necesita el entero apuntado por p

Elpunterodejadecontenerunadirecciónválidaynosedebeaccederatravésdeélhastaquenocontenganuevamenteotradirecciónválida.

Page 27: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

27

Luis Hernández Yáñez

Montón(heap)Montón(heap)

Página 52Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;cout << *p1 << endl;cout << *p2 << endl;cout << *p3 << endl;delete p2;delete p3;

return 0;}

dinamicas.cpp

1.5aa

p1p1

p2p2

p3p3

Identificadores:

4(a,p1,p2,p3)

Variables:

6(+*p2 y*p3)

Identificadores:

4(a,p1,p2,p3)

Variables:

6(+*p2 y*p3)

1.51.5

123.45123.45

Luis Hernández Yáñez

Página 53Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;

PILA

a 1.5

p1 ?

p2 ?

p3 ?

MONTÓN

Page 28: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

28

Luis Hernández Yáñez

Página 54Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;

PILA

a 1.5

p1

p2 ?

p3 ?

MONTÓN

Luis Hernández Yáñez

Página 55Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;

PILA

a 1.5

p1

p2

p3 ?

MONTÓN

Page 29: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

29

Luis Hernández Yáñez

Página 56Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;

PILA

a 1.5

p1

p2

p3 ?

1.5

MONTÓN

Luis Hernández Yáñez

Página 57Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;

PILA

a 1.5

p1

p2

p3

1.5

MONTÓN

Page 30: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

30

Luis Hernández Yáñez

Página 58Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;

PILA

a 1.5

p1

p2

p3

123.45

1.5

MONTÓN

Luis Hernández Yáñez

Página 59Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;cout << *p1 << endl;cout << *p2 << endl;cout << *p3 << endl;delete p2;

PILA

a 1.5

p1

p2 ?

p3

123.45

MONTÓN

Page 31: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

31

Luis Hernández Yáñez

Página 60Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodevariablesdinámicas#include <iostream>using namespace std;

int main() {double a = 1.5;double *p1, *p2, *p3;p1 = &a;p2 = new double;*p2 = *p1;p3 = new double;*p3 = 123.45;cout << *p1 << endl;cout << *p2 << endl;cout << *p3 << endl;delete p2;delete p3;

PILA

a 1.5

p1

p2 ?

p3 ?

MONTÓN

Luis Hernández Yáñez

Página 61Fundamentos de la programación: Punteros y memoria dinámica

Page 32: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

32

Luis Hernández Yáñez

Página 62Fundamentos de la programación: Punteros y memoria dinámica

ErroresdeasignacióndememoriaParaaprovecharbienlamemoriaquedejalibrelamemoriaprincipal,lapilayelmontóncrecenendireccionesopuestas.

Amedidaquesellamaafuncioneslapilacrece.

Amedidaquesecreandatosdinámicoselmontóncrece.

Siloslímitesdeambasregionesdememoriaseencuentran,seproduceunacolisiónpila‐montón.

Elprogramafallaporquenosepuedencrearmásdatosdinámicosnisepuedenrealizarmásllamadasafunciones.

Normalmentelapilasueleteneruntamañomáximoestablecidoquenopuedesobrepasaraunqueelmontónnoestéutilizandoelresto.Silosobrepasaloqueseproduceesundesbordamientodelapila.

Pila

Montón

Luis Hernández Yáñez

Página 63Fundamentos de la programación: Punteros y memoria dinámica

GestióndelmontónElSistemadeGestióndeMemoriaDinámica(SGMD)seencargadelocalizarenelmontónunbloquesuficientementegrandeparaalojarlavariablequesepidacrearysiguelapistadelosbloquesdisponibles.

Peronodisponedeunrecolectordebasura,comoellenguajeJava.

Esnuestraresponsabilidaddevolveralmontóntodalamemoriautilizadapornuestrasvariablesdinámicasunavezquenosenecesitan.

Losprogramasdebenasegurarsededestruir,coneloperadordelete,todaslasvariablespreviamentecreadasconeloperadornew.

Lacantidaddememoriadisponibleenelmontóndebeserexactamentelamismaantesydespuésdelaejecucióndelprograma.

Ysiempredebehaberalgunaforma(puntero)deaccederacadadatodinámico.Esungraveerrorperder undatoenelmontón.

Page 33: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

33

Luis Hernández Yáñez

Página 64Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Página 65Fundamentos de la programación: Punteros y memoria dinámica

InicializaciónconeloperadornewEloperadornew admiteunvalorinicialparaeldatodinámicocreado:int *p;p = new int(12);

Secrealavariabledinámica,detipoint,yseinicializaconelvalor12.#include <iostream>using namespace std;#include "registro.h"

int main() {tRegistro reg;reg = nuevo();tRegistro *punt = new tRegistro(reg);mostrar(*punt);delete punt;return 0;

}

registros.cpp

Page 34: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

34

Luis Hernández Yáñez

Página 66Fundamentos de la programación: Punteros y memoria dinámica

Luis Hernández Yáñez

Página 67Fundamentos de la programación: Punteros y memoria dinámica

MalusodelamemoriadinámicaIOlvidodedestruccióndeundatodinámico:...int main() {

tRegistro *p;p = new tRegistro;*p = nuevo();mostrar(*p);

return 0;}

G++nodaráningunaindicacióndelerroryelprogramapareceráterminarcorrectamente,perodejarámemoriadesperdiciada.

VisualC++sícompruebaelusodelamemoriadinámicaynosavisasidejamosmemoriasinliberar.

Faltadelete p;Faltadelete p;

Page 35: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

35

Luis Hernández Yáñez

Página 68Fundamentos de la programación: Punteros y memoria dinámica

MalusodelamemoriadinámicaIIIntentodedestruccióndeundatodinámicoinexistente:...int main() {

tRegistro *p1 = new tRegistro;*p1 = nuevo();mostrar(*p1);tRegistro *p2;p2 = p1;mostrar(*p2);delete p1;delete p2;

return 0;}

tRegistrop1p1

p2p2

Sólosehacreadounavariabledinámica Nosepuedendestruir2

Sólosehacreadounavariabledinámica Nosepuedendestruir2

Luis Hernández Yáñez

¡Perdido!

Página 69Fundamentos de la programación: Punteros y memoria dinámica

MalusodelamemoriadinámicaIIIPérdidadeundatodinámico:...int main() {

tRegistro *p1, *p2;p1 = new tRegistro(nuevo());p2 = new tRegistro(nuevo());

mostrar(*p1);p1 = p2;mostrar(*p1);

delete p1;delete p2;

return 0;}

tRegistrop2p2

p1p1

p1 dejadeapuntaraldatodinámicoquesecreóconél Sepierdeesedatoenelmontón

p1 dejadeapuntaraldatodinámicoquesecreóconél Sepierdeesedatoenelmontón

tRegistro

Page 36: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

36

Luis Hernández Yáñez

Página 70Fundamentos de la programación: Punteros y memoria dinámica

MalusodelamemoriadinámicaIVIntentodeaccesoaundatodinámicotrassueliminación:...int main() {

tRegistro *p;p = new tRegistro(nuevo());

mostrar(*p);delete p;...mostrar(*p);

return 0;}

p hadejadodeapuntaraldatodinámicodestruido Intentodeaccesoamemoriainexistentep hadejadodeapuntaraldatodinámicodestruido Intentodeaccesoamemoriainexistente

Luis Hernández Yáñez

Página 71Fundamentos de la programación: Punteros y memoria dinámica

Page 37: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

37

Luis Hernández Yáñez

Página 72Fundamentos de la programación: Punteros y memoria dinámica

Arraysdepunterosadatosdinámicostypedef char tCadena[80];typedef struct {

int codigo;tCadena nombre;double valor;

} tRegistro;typedef tRegistro *tRegPtr;

const int N = 1000;

// Array de punteros a registros:typedef tRegPtr tArray[N];typedef struct {

tArray registros;int cont;

} tLista;

Lospunterosocupanmuypocoenmemoria.

Losdatosalosqueapuntenseguardaránenelmontón.

Secrearánamedidaqueseinsertenenlalista.

Sedestruiránamedidaqueseeliminendelalista.

Lospunterosocupanmuypocoenmemoria.

Losdatosalosqueapuntenseguardaránenelmontón.

Secrearánamedidaqueseinsertenenlalista.

Sedestruiránamedidaqueseeliminendelalista.

Luis Hernández Yáñez

Página 73Fundamentos de la programación: Punteros y memoria dinámica

ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;

0 1 2 3 4 5 6 998 999

lista.registroslista.registros

0lista.contlista.cont

Page 38: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

38

Luis Hernández Yáñez

Página 74Fundamentos de la programación: Punteros y memoria dinámica

ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;

0 1 2 3 4 5 6 998 999

lista.registroslista.registros

1lista.contlista.cont

Luis Hernández Yáñez

Página 75Fundamentos de la programación: Punteros y memoria dinámica

ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;

0 1 2 3 4 5 6 998 999

lista.registroslista.registros

2lista.contlista.cont

Page 39: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

39

Luis Hernández Yáñez

Página 76Fundamentos de la programación: Punteros y memoria dinámica

ArraysdepunterosadatosdinámicostLista lista;lista.cont = 0;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;lista.registros[lista.cont] = new tRegistro(nuevo());lista.cont++;

0 1 2 3 4 5 6 998 999

lista.registroslista.registros

3lista.contlista.cont

Luis Hernández Yáñez

Página 77Fundamentos de la programación: Punteros y memoria dinámica

ArraysdepunterosadatosdinámicosLosregistrosseaccedenatravésdepunteros(operadorflecha):cout << lista.registros[0]‐>nombre;

0 1 2 3 4 5 6 998 999

lista.registroslista.registros

3lista.contlista.cont

Page 40: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

40

Luis Hernández Yáñez

Página 78Fundamentos de la programación: Punteros y memoria dinámica

ArraysdepunterosadatosdinámicosNohayqueolvidarsededevolverlamemoriaalmontón:for (int i = 0; i < lista.cont; i++)

delete lista.registros[i];

0 1 2 3 4 5 6 998 999

lista.registroslista.registros

3lista.contlista.cont

Luis Hernández Yáñez

Página 79Fundamentos de la programación: Punteros y memoria dinámica

Implementacióndelalistadinámica#ifndef LISTA_H#define LISTA_H#include "registro.h"

const int N = 1000;typedef tRegPtr tArray[N];typedef struct {

tArray registros;int cont;

} tLista;

const char BD[] = "bd.dat";

void mostrar(const tLista &lista);bool insertar(tLista &lista, tRegistro registro);bool eliminar(tLista &lista, int code);int buscar(tLista lista, int code);bool cargar(tLista &lista);void guardar(tLista lista);void destruir(tLista &lista);

#endif

lista.h

Page 41: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

41

Luis Hernández Yáñez

Implementacióndelalistadinámica...bool insertar(tLista &lista, tRegistro registro) {

bool ok = true;if (lista.cont == N) ok = false;else {

lista.registros[lista.cont] = new tRegistro(registro);lista.cont++;

}return ok;

}

bool eliminar(tLista &lista, int code) {bool ok = true;int ind = buscar(lista, code);if (ind == ‐1) ok = false;else {

delete lista.registros[ind];for (int i = ind + 1; i < lista.cont; i++)

lista.registros[i ‐ 1] = lista.registros[i];lista.cont‐‐;

}return ok;

} ...

Página 80Fundamentos de la programación: Punteros y memoria dinámica

lista.cpp

Luis Hernández Yáñez

Página 81Fundamentos de la programación: Punteros y memoria dinámica

Implementacióndelalistadinámicaint buscar(tLista lista, int code) {// Devuelve el índice o ‐1 si no se ha encontrado

int ind = 0;bool encontrado = false;while ((ind < lista.cont) && !encontrado)

if (lista.registros[ind]‐>codigo == code) encontrado = true;else ind++;

if (!encontrado) ind = ‐1;return ind;

}

void mostrar(const tLista &lista) {cout << endl << "Elementos de la lista:" << endl

<< "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐" << endl;for (int i = 0; i < lista.cont; i++)

mostrar(*lista.registros[i]);}

void destruir(tLista &lista) {for (int i = 0; i < lista.cont; i++)

delete lista.registros[i];lista.cont = 0;

} ...

Page 42: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

42

Luis Hernández Yáñez

Página 82Fundamentos de la programación: Punteros y memoria dinámica

Implementacióndelalistadinámica#include <iostream>using namespace std;#include "registro.h"#include "lista.h"

int main() {tLista lista;if (cargar(lista)) {

mostrar(lista);destruir(lista);

}

return 0;}

listadinamica.cpp

Luis Hernández Yáñez

Página 83Fundamentos de la programación: Punteros y memoria dinámica

Page 43: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

43

Luis Hernández Yáñez

Página 84Fundamentos de la programación: Punteros y memoria dinámica

DestruccióndelarraydinámicoDestruccióndelarraydinámico

CreaciónydestruccióndearraysdinámicosUnarraydinámicoesunarraydedatosdinámicosparaelquesecreantodoslosdatosdinámicosautomáticamentealdeclararlo:int *p = new int[10];

Secreanlas10variablesdinámicas,detipoint.Seaccedenconp[i].#include <iostream>using namespace std;const int N = 10;

int main() {int *p = new int[N];for (int i = 0; i < N; i++) p[i] = i;for (int i = 0; i < N; i++) cout << p[i] << endl;delete [] p;

return 0;}

Luis Hernández Yáñez

Página 85Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodearraydinámico...#include "registro.h"

const int N = 1000;

// Lista: array dinámico y contadortypedef struct {

tRegPtr registros;int cont;

} tLista;

...

listaAD.h

Page 44: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

44

Luis Hernández Yáñez

Página 86Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodearraydinámico

bool insertar(tLista &lista, tRegistro registro) {

bool ok = true;

if (lista.cont == N) ok = false;

else {

lista.registros[lista.cont] = registro;

lista.cont++;

}

return ok;

}

bool eliminar(tLista &lista, int code) {

bool ok = true;

int ind = buscar(lista, code);

if (ind == ‐1) ok = false;

else {

for (int i = ind + 1; i < lista.cont; i++)

lista.registros[i ‐ 1] = lista.registros[i];

lista.cont‐‐;

}

return ok;

} ...

listaAD.cpp

Nousamosnew,puessehancreadotodoslosregistrosanteriormente

Nousamosnew,puessehancreadotodoslosregistrosanteriormente

Nousamosdelete,puessedestruyentodoslosregistrosalfinal

Nousamosdelete,puessedestruyentodoslosregistrosalfinal

Luis Hernández Yáñez

Página 87Fundamentos de la programación: Punteros y memoria dinámica

Usamospuntoenlugarde‐>Usamospuntoenlugarde‐>

AccesocomoarrayAccesocomoarray

SedestruyentodosalavezSedestruyentodosalavez

Ejemplodearraydinámico

int buscar(tLista lista, int code) {

int ind = 0;

bool encontrado = false;

while ((ind < lista.cont) && !encontrado)

if (lista.registros[ind].codigo == code) encontrado = true;

else ind++;

if (!encontrado) ind = ‐1;

return ind;

}

void mostrar(const tLista &lista) {

cout << endl

<< "Elementos de la lista:" << endl

<< "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐" << endl;

for (int i = 0; i < lista.cont; i++)

mostrar(lista.registros[i]);

}

void destruir(tLista &lista) {

delete [] lista.registros;

lista.cont = 0;

} ...

Page 45: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

45

Luis Hernández Yáñez

Página 88Fundamentos de la programación: Punteros y memoria dinámica

SecreantodosalavezSecreantodosalavez

Ejemplodearraydinámicobool cargar(tLista &lista) {

bool ok = true;ifstream archivo;archivo.open(BD);if (!archivo.is_open()) ok = false;else {

tRegistro registro;lista.cont = 0;lista.registros = new tRegistro[N];archivo >> registro.codigo;while ((registro.codigo != ‐1) && (lista.cont < N)) {

archivo >> registro.valor;archivo.getline(registro.nombre, 80);lista.registros[lista.cont] = registro;lista.cont++;archivo >> registro.codigo;

}archivo.close();

} ...

Luis Hernández Yáñez

Página 89Fundamentos de la programación: Punteros y memoria dinámica

Ejemplodearraydinámicovoid guardar(tLista lista) {

ofstream archivo;archivo.open(BD);for (int i = 0; i < lista.cont; i++) {

archivo << lista.registros[i].codigo << " ";archivo << lista.registros[i].valor;archivo << lista.registros[i].nombre << endl;

}archivo.close();

}

Mismoprogramaprincipalqueeldelarraydedatosdinámicos,peroincluyendolistaAD.h,enlugardelista.h.

ejemploAD.cpp

Page 46: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

46

Luis Hernández Yáñez

Página 90Fundamentos de la programación: Punteros y memoria dinámica

Losarraysdedatosdinámicosvantomandodelmontónmemoriaamedidaquelanecesitan,mientrasqueelarraydinámicosecreaenteroenelmontón:

Montón

0 1 2 3 4 5 6 7

0 1 2 3 4 5 6 7

Arraydedatosdinámicos:Arraydepunteros

Arraydedatosdinámicos:Arraydepunteros

Arraydinámico:Puntero(direccióndearray)

Arraydinámico:Puntero(direccióndearray)

Luis Hernández Yáñez

C++:An Introduction to Computing (2ªedición)J.Adams,S.Leestma,L.Nyhoff.Prentice Hall,1998

EllenguajedeprogramaciónC++ (Ediciónespecial)B.Stroustrup.Addison‐Wesley,2002

ProgramaciónenC++paraingenierosF.Xhafa etal.Thomson,2006

Fundamentos de la programación: Punteros y memoria dinámica Página 91

Page 47: Fundamentos de la programación 2013 2014 9 · Al copiarle otro puntero (con el mismo tipo base) que ya contenga una dirección válida. Al asignarle la dirección de otro dato con

13/05/2014

47

Luis Hernández Yáñez

LicenciaCC(Creative Commons)Estetipodelicenciasofrecenalgunosderechosaterceraspersonasbajociertascondiciones.

Estedocumentotieneestablecidaslassiguientes:

Pulsaenlaimagendearribaaladerechaparasabermás.

Fundamentos de la programación: Punteros y memoria dinámica Página 92

Reconocimiento(Attribution):Encualquierexplotacióndelaobraautorizadaporlalicenciaharáfaltareconocerlaautoría.

Nocomercial(Noncommercial):Laexplotacióndelaobraquedalimitadaausosnocomerciales.

Compartirigual(Sharealike):Laexplotaciónautorizadaincluyelacreacióndeobrasderivadassiemprequemantenganlamismalicenciaalserdivulgadas.