Es un lenguaje de programación de propósito general, orientado a objetos, y una extensión de C. Es ampliamente utilizado en el desarrollo de software de sistemas, aplicaciones y videojuegos.
Introducción a C++
Compilar un programa C++
Utiliza un compilador como g++
o clang++
para compilar archivos .cpp
.
g++ programa.cpp -o programa
Estructura básica de un programa
#include <iostream>
using namespace std;
int main() {
cout << "Hola, Mundo!" << endl;
return 0;
}
Comentarios
Para escribir comentarios de una línea o múltiples líneas.
// Comentario de una sola línea
/*
Comentario de múltiples líneas
*/
Namespaces
Los namespaces organizan código y evitan colisiones de nombres.
namespace MiEspacio {
int valor = 10;
}
cout << MiEspacio::valor;
El más común es std
.
using namespace std; // Evita tener que escribir std:: delante de cada función de la librería estándar.
Módulos
Permiten dividir programas en módulos más gestionables y eficientes.
export module math;
export int suma(int a, int b) { return a + b; }
Variables y tipos
Tipos primitivos
Los tipos básicos incluyen:
int
: Enterosfloat
: Números de coma flotantedouble
: Números de doble precisiónchar
: Caracteresbool
: Booleanos (true
ofalse
)
Modificadores de tipos
Los modificadores amplían los tipos de datos primitivos.
short
: Entero pequeñolong
: Entero grandeunsigned
: Sin signo (solo valores positivos)
Expresiones constantes
Permiten evaluar funciones o variables en tiempo de compilación.
constexpr int square(int x) { return x * x; }
constexpr int result = square(5); // Evaluado en tiempo de compilación
Declaración automática de tipos
Permite que el compilador deduzca el tipo de la variable.
auto x = 10; // x es de tipo int
auto y = 3.14; // y es de tipo double
Constinit
Garantiza que una variable global sea inicializada en tiempo de compilación.
constinit int x = 42;
Operadores
Operadores aritméticos
Suma (+
), resta (-
), multiplicación (*
), división (/
), módulo (%
).
Operadores relacionales
Igualdad (==
), desigualdad (!=
), mayor (>
), menor (<
), mayor o igual (>=
), menor o igual (<=
).
Operadores lógicos
Y lógico (&&
), O lógico (||
), negación (!
).
Operadores de asignación
Igual (=
), suma-asignación (+=
), resta-asignación (-=
), etc.
Spaceship operator (<=>
)
Permite realizar comparaciones completas.
#include <compare>
int a = 1, b = 2;
auto result = a <=> b;
Entrada y Salida
Salida con cout
Muestra datos en la consola.
cout << "Valor: " << variable << endl;
Entrada con cin
Captura datos del usuario.
int numero;
cin >> numero;
Control de Flujo
Condicionales
If - Else
Evalúa una condición y ejecuta el código dependiendo del resultado.
if (condicion) {
// código si verdadero
} else {
// código si falso
}
Switch
Estructura para manejar múltiples casos.
switch (valor) {
case 1:
// código para caso 1
break;
case 2:
// código para caso 2
break;
default:
// código para otros casos
}
Bucles
Bucle For
Se utiliza para iteraciones controladas.
for (int i = 0; i < 10; i++) {
cout << i << endl;
}
Bucle While
Repite mientras una condición es verdadera.
int i = 0;
while (i < 10) {
cout << i << endl;
i++;
}
Bucle Do-While
Garantiza al menos una ejecución del bloque de código.
int i = 0;
do {
cout << i << endl;
i++;
} while (i < 10);
Bucles for basados en rango
Facilitan la iteración sobre contenedores.
std::vector<int> vec = {1, 2, 3};
for (auto &v : vec) {
std::cout << v << std::endl;
}
Funciones
Declaración de funciones
Una función recibe parámetros, realiza una tarea y opcionalmente devuelve un valor.
int sumar(int a, int b) {
return a + b;
}
Prototipo de función
Declarar la función antes de main()
y definirla después de main()
.
int sumar(int a, int b); // Prototipo
int main() {
cout << sumar(5, 3) << endl;
return 0;
}
int sumar(int a, int b) {
return a + b;
}
Sobrecarga de funciones
Permite definir varias funciones con el mismo nombre, pero diferentes parámetros.
int suma(int a, int b) { return a + b; }
float suma(float a, float b) { return a + b; }
Funciones con valores por defecto
int multiplicar(int a, int b = 2) {
return a * b;
}
Funciones lambda
Permiten definir funciones anónimas en línea, muy útil para callbacks o para usar en algoritmos.
auto sum = [](int a, int b) { return a + b; };
std::cout << sum(5, 3); // Imprime 8
Colecciones
Arrays
Declaración y acceso a arrays
int arr[5] = {1, 2, 3, 4, 5};
cout << arr[0]; // Imprime 1
Contenedores STL
Contenedores comunes del STL (Standard Template Library)
- Vector: Arreglo dinámico.
- Map: Estructura de datos de clave-valor.
- Set: Conjunto de elementos únicos.
#include <vector>
#include <map>
#include <set>
std::vector<int> vec = {1, 2, 3};
std::map<int, std::string> mapa = {{1, "Uno"}, {2, "Dos"}};
std::set<int> conjunto = {1, 2, 3};
Inicialización de listas
Permite inicializar contenedores o variables directamente usando llaves {}
.
std::vector<int> vec = {1, 2, 3, 4, 5};
int arr[] = {1, 2, 3};
Iteradores
Facilitan la navegación por contenedores.
std::vector<int> vec = {1, 2, 3};
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << std::endl;
}
Rangos
Permiten operaciones más expresivas sobre contenedores.
#include <ranges>
std::vector<int> nums = {1, 2, 3, 4, 5};
auto even_nums = nums | std::ranges::views::filter([](int n) { return n % 2 == 0; });
Punteros
Punteros
Un puntero almacena la dirección de una variable.
int x = 10;
int* p = &x; // p apunta a la dirección de x
cout << *p; // Imprime el valor de x
Uso de nullptr
Se usa en lugar de NULL
para representar un puntero nulo de manera más segura.
int* p = nullptr; // Mejor que usar NULL
Punteros inteligentes
Los punteros inteligentes como std::unique_ptr
y std::shared_ptr
gestionan la memoria automáticamente, evitando fugas de memoria.
#include <memory>
std::unique_ptr<int> ptr = std::make_unique<int>(10); // C++14 en adelante
std::shared_ptr<int> sharedPtr = std::make_shared<int>(20);
Move semantics
Optimiza el rendimiento evitando copias innecesarias.
class MiClase {
public:
MiClase(const MiClase&) = delete; // Evita copias
MiClase(MiClase&&) = default; // Permite movimientos
};
Referencias
Concepto de Referencias
Las referencias son alias para variables existentes. Permiten manipular el valor de la variable original sin crear una copia.
int original = 30;
int &ref = original; // ref es una referencia a original
- Los cambios en la referencia afectan a la variable original.
- Las referencias son útiles para pasar grandes estructuras de datos a funciones sin hacer copias.
Manejo de Memoria Dinámica
new
y delete
Se utilizan para reservar y liberar memoria en el heap.
int* p = new int; // Reserva memoria
*p = 10;
delete p; // Libera memoria
Arrays dinámicos
int* arr = new int[5]; // Reserva un array
delete[] arr; // Libera el array
Clases y programación orientada a objetos
Definición de clase
Una clase es una plantilla para crear objetos.
class Persona {
public:
string nombre;
int edad;
void saludar() {
cout << "Hola, soy " << nombre << endl;
}
};
Creación de objetos
Persona p;
p.nombre = "Luis";
p.edad = 25;
p.saludar();
Constructor
Inicializa un objeto al crearlo.
class Persona {
public:
string nombre;
Persona(string n) {
nombre = n;
}
};
Destructor
Limpia el objeto cuando deja de ser necesario.
~Persona() {
cout << "Objeto destruido" << endl;
}
Herencia simple
Una clase puede heredar atributos y métodos de otra.
class Estudiante : public Persona {
public:
int matricula;
};
Polimorfismo con clases
Permite usar una misma interfaz para distintos tipos de objetos.
class Animal {
public:
virtual void hacerSonido() const { std::cout << "Sonido de animal" << std::endl; }
};
class Perro : public Animal {
public:
void hacerSonido() const override { std::cout << "Guau!" << std::endl; }
};
Excepciones
Bloques try-catch
Manejan excepciones
try {
throw std::runtime_error("Error");
} catch (const std::exception &e) {
std::cout << "Excepción capturada: " << e.what() << std::endl;
}
Lanzar excepciones
Puedes lanzar excepciones en C++ usando throw
.
void divide(int a, int b) {
if (b == 0) {
throw std::invalid_argument("División por cero");
}
std::cout << a / b << std::endl;
}
Librerías Estándar
iostream
Proporciona funciones para entrada y salida.
#include <iostream>
using namespace std;
cout << "Hola" << endl;
cin >> variable;
vector
Una estructura de datos dinámica que puede cambiar de tamaño.
#include <vector>
vector<int> v = {1, 2, 3};
v.push_back(4);
cout << v[0]; // Imprime 1
algorithm
Ofrece funciones de algoritmos como búsqueda y ordenación.
#include <algorithm>
vector<int> v = {4, 1, 3, 2};
sort(v.begin(), v.end()); // Ordena el vector
Macros y Plantillas
Macros
Definen funciones o valores constantes preprocesadas.
#define PI 3.14159
#define cuadrado(x) ((x) * (x))
Función plantilla
Permite definir funciones genéricas que operan con cualquier tipo de datos.
template <typename T>
T sumar(T a, T b) {
return a + b;
}
Clase plantilla
Define clases genéricas.
template <class T>
class Caja {
public:
T valor;
Caja(T v) : valor(v) {}
};
Conceptos
Son restricciones que permiten definir interfaces claras para plantillas.
template <typename T>
concept Numerico = std::is_arithmetic_v<T>;
template <Numerico T>
T multiplicar(T a, T b) {
return a * b;
}
Archivos
Lectura y escritura de archivos
Se utilizan ifstream
para lectura y ofstream
para escritura.
#include <fstream>
ofstream archivo("salida.txt");
archivo << "Hola Archivo" << endl;
archivo.close();
ifstream entrada("entrada.txt");
string linea;
while (getline(entrada, linea)) {
cout << linea << endl;
}
entrada.close();
Concurrencia
Threads
Manejo de hilos con std::thread
#include <thread>
void funcion() {
std::cout << "Hilo en ejecución" << std::endl;
}
int main() {
std::thread hilo(funcion); // Crear un nuevo hilo
hilo.join(); // Esperar a que el hilo termine
}
Mutex y condiciones
Sincronización con mutex
#include <mutex>
std::mutex mtx;
void imprimir(int i) {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Valor: " << i << std::endl;
}
Corutinas
Permiten suspender y reanudar funciones.
#include <coroutine>
std::future<void> ejemplo() {
co_await std::chrono::seconds(1);
std::cout << "Hecho!" << std::endl;
}
Gestión de Errores y Depuración
assert
para depuración
Verifica condiciones en tiempo de ejecución.
#include <cassert>
int x = 5;
assert(x == 5); // Pasa, no ocurre nada
cerr
para errores
Muestra mensajes de error en la salida estándar de errores
cerr << "Error: Variable inválida" << endl;