Memoria dinámica
El manejo de memoria
Punteros
Usando punteros
Estructuras de datos
Estructuras de datos
Creando nuestra primera estructura
Uniones y enumeraciones
Introducción a la Programación Orientada a Objetos
Qué es la Programación Orientada a Objetos
Creando nuestro primer objeto
El ciclo de vida de un objeto
Principios de la Programación Orientada a Objetos
Encapsulación
This
Static
Herencia
Herencia múltiple
Polimorfismo
Despedida
Conclusiones del curso
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
En el mundo de la programación, la capacidad de definir nuestras propias estructuras de datos y tipos personalizados enriquece la funcionalidad y versatilidad de nuestras aplicaciones. ¿Alguna vez te has preguntado cómo manejar datos de manera más eficiente en C++? Hoy exploraremos cómo aprovechar los punteros y la flexibilidad de C++ para trabajar con estructuras de datos complejas y personalizadas.
Hasta ahora, hemos utilizado listas para manejar elementos de un mismo tipo. Sin embargo, estas listas presentan ciertas limitaciones:
sizeof
.Al trabajar con listas de caracteres, por ejemplo, tuvimos que utilizar la librería string
para una mejor manipulación. Sin embargo, C++ nos ofrece formas más sofisticadas para definir estructuras de datos versátiles.
Veamos un ejemplo clásico de cómo definimos una lista de caracteres en C++:
char texto[] = {'h', 'o', 'l', 'a'};
Aquí hemos creado una lista de caracteres llamada texto
. El compilador identifica que es una lista gracias a los corchetes y reconoce que es del tipo char
. Sin embargo, podríamos simplificar esta escritura:
char texto[] = "hola";
Ambas formas son válidas, pero la última es más directa. El compilador reconoce las comillas dobles como una indicación de cadena de caracteres.
En C++, los punteros son fundamentales para entender cómo los datos son almacenados y accedidos en memoria. Cuando definimos una lista de caracteres, el compilador asigna cada carácter a una dirección de memoria única. Por ejemplo, para la cadena "hola":
h
se almacena en la dirección 0.o
en la 1.l
en la 2.a
en la 3.Además, C++ utiliza un carácter especial en la tabla ASCII, el diagonal invertida cero (\0
), para indicar el final de una cadena de caracteres. Esto ocurre cuando se alcanza una nueva dirección de memoria después de los caracteres.
Supongamos que queremos manejar una entidad más compleja, como una persona. En este caso, necesitamos almacenar diversos datos, como el nombre y la edad. Podemos lograrlo definiendo una estructura:
struct Persona {
char nombre[50];
int edad;
};
Con esta estructura, hemos definido campos para el nombre
y la edad
. Estos datos se almacenan en secciones específicas de memoria, lo que permite un acceso eficiente:
Es interesante notar que la dirección de memoria de la estructura Persona
coincide con la dirección del primer campo, que en este caso es el nombre
.
Los punteros proporcionan una forma flexible de manejar datos en C++. Permiten:
Al sumar estas características, los punteros son cruciales para trabajar con datos complejos de manera eficaz.
En resumen, la habilidad de definir nuestras propias estructuras de datos y comprender la gestión de la memoria en C++ nos permite crear aplicaciones más potentes y flexibles. ¡Te animamos a seguir explorando estas herramientas y mejorar tu dominio de C++!
Aportes 11
Preguntas 3
Si bien sabemos que la cadena de caracteres no es mas que un arreglo pero del tipo de dato Char, me pregunte si en un arreglo de enteros unidimensional o bidimensional cada uno de los elementos de mi arreglo tenían su propia dirección de memoria. Para eso hice el siguiente código para revisar cada dirección de memoria.
#include <iostream>
using namespace std;
int main()
{
/*La duda es que si en un array cada elemento del mismo tiene un dirección de memoria única
Para ver si es así usaremos punteros para ver si cada dirección de memoria del array es distinta*/
//Primero creo un array unidimensional con sus elementos ya definidos
int Arreglo [4]={1,2,3,4};
//Defino un puntero entero que ira mostrando cada una de las direcciones
for (int i = 0; i < 4; i++)
{
int *puntero= &Arreglo[i];
cout<<"El valor "<<*puntero<<" tiene la direccion "<<puntero<<endl;
}
cout<<"Para mi arreglo Bidimensional "<<endl;
int Bidimensional [2][2]={{1,2},{3,4}};
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
int *puntero= &Bidimensional[i][j];
cout<<"El valor "<<*puntero<<" tiene la direccion "<<puntero<<endl;
}
}
}
El resultado que dio la consola fue el siguiente:
El valor 1 tiene la direccion 0x6ffde0
El valor 2 tiene la direccion 0x6ffde4
El valor 3 tiene la direccion 0x6ffde8
El valor 4 tiene la direccion 0x6ffdec
Para mi arreglo Bidimensional
El valor 1 tiene la direccion 0x6ffdd0
El valor 2 tiene la direccion 0x6ffdd4
El valor 3 tiene la direccion 0x6ffdd8
El valor 4 tiene la direccion 0x6ffddc
Por lo tanto en arreglos Bidimensionales y Unidimensionales cada elementos tiene su propia dirección de memoria.
Genial, siempre es bueno entrar a escribir código con algo de contexto previo.
Un ejemplo obteniendo la direccion de memoria de cada elemento de un array.
.
Es cómico como la dirección de memoria abarca desde 0x2020 hasta 0x2026
XD
La dirección de memoria de la instancia de una clase u objeto es la primera del segmento asignado a esta. Los objetos son asignados un segmento de direcciones de memoria para almacenar valores para sus atributos.
Comparativa de tipos de declaración:
#include <iostream>
using namespace std;
int main() {
/*
Note: This isn't the most efficient way
to manage text as it is easier to do so
using the string library.
*/
// create (static) array the normie way
char text[] = {'h', 'o', 'l', 'a'};
// create (static) array the simplified way
char text2[] = "hola";
// create (static) array using pointers
char *text3 = (char *)"hola";
cout << text[0] << endl; // output: h
cout << text2[0] << endl; // output: h
cout << text3[0] << endl; //output: h
Importante: Cada carácter de una lista de carácteres es almacenado en una dirección de memoria (RAM) y se usa un carácter vacío denotado como “\0” para indicar el final de la lista.
Les comparto mi código jejeje:
#include <iostream>
using namespace std;
int main(){
int puntero[] = {1,3,5,6,7,8,9};
cout<<sizeof(puntero)/sizeof(int)<<" datos en la lista"<<endl<<"Accediendo a los datos de la memoria..."<<endl;
cout<<"Direcciones de la memoria de cada valor: "<<endl;
//ciclo for para mostrar datos de la memoria
for(int i = 0;i<sizeof(puntero)/sizeof(int);i++) {
/*Aquí establecí variables para saber de donde esta saliendo cada valor y poder entender*/
int valor = puntero[i];
int *direccion = &puntero[i];
cout<<"Index: " <<i<<", Valor: "<<valor<<", Dirección: "<<direccion<<endl;
}
cout<<"-----------Proceso Terminado-------";
}
bueno el contenido, peor creo que lo más correcto sería decir arreglos, en vez de listas 😃
Minuto 4:05, la ilustración es técnicamente imprecisa pues representa a un número con una celda de memoria (1 byte) cuando un int ocupa 4 celdas de memoria (4 bytes, de −2,147,483,648 hasta 2,147,483,647), a menos que se use el tipo std::byte que sí ocupa un byte exacto, lo cual es improbable porque este tipo no forma parte del estándar de C/C++.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?