Hoja de ruta · en continua actualización

Hoja de ruta de C++ moderno: C++11 → C++23

La mayoría del material para principiantes enseña el C++ de 2003. El código real de 2026 no se parece a eso. Este es el orden en que conviene incorporar las características modernas: cada entrada te muestra la forma antigua, la nueva y por qué importa.

Nota: nuestro editor en el navegador solo cubre el núcleo didáctico (no admite std::string, vector ni características de C++11 o posteriores). Los fragmentos de abajo son para tu compilador de escritorio — consulta cómo compilar C++ (EN).

Etapa 1 — C++11/14: la base (empieza por estas)

Estas no son «avanzadas». Cualquier compilador de la última década las admite y todos los proyectos profesionales las usan. Si un tutorial no las enseña, te está enseñando una pieza de museo.

1. auto — deja que el compilador nombre el tipo

// antiguo
std::vector<std::string>::iterator it = names.begin();

// moderno
auto it = names.begin();          // tipo deducido, sigue siendo tipado estático

Por qué: los tipos se vuelven largos y ruidosos; auto mantiene el tipo correcto incluso cuando cambias el contenedor. Sigue siendo tipado estático — no ocurre nada en tiempo de ejecución.

2. for basado en rangos — itera sin malabares con índices

// antiguo
for (size_t i = 0; i < v.size(); ++i) sum += v[i];

// moderno
for (int x : v) sum += x;

// solo lectura, sin copia — el patrón que verás en todas partes
for (const auto& name : names) cout << name << '\n';

Por qué: sin errores de desfase de uno, sin variable de índice. const auto& debería ser tu opción por defecto: sin copia y sin modificaciones accidentales.

3. Punteros inteligentes — deja de llamar a new/delete a mano

// antiguo — propenso a fugas, inseguro ante excepciones
Widget* w = new Widget();
... // si esto lanza una excepción, w queda sin liberar
delete w;

// moderno — la propiedad es explícita en el tipo
auto w = std::make_unique<Widget>();   // único propietario, se libera automáticamente
auto s = std::make_shared<Widget>();   // propiedad compartida (úsala con moderación)

Por qué: RAII en una línea. unique_ptr debería ser tu opción por defecto para objetos en el heap; shared_ptr, solo cuando la propiedad sea realmente compartida.

4. Lambdas — pasa comportamiento, no solo datos

// ordena con una regla propia, sin escribir una función con nombre
std::sort(people.begin(), people.end(),
          [](const Person& a, const Person& b) { return a.age < b.age; });

// captura el estado local por valor ([x]) o por referencia ([&x])
int threshold = 30;
auto over = [threshold](int age) { return age > threshold; };

Por qué: las lambdas convirtieron «pasar una función pequeña» en algo idiomático y abrieron la puerta a los algoritmos modernos. Te las encontrarás en cualquier base de código escrita después de 2011.

5. nullptr, enum class, constexpr

char* p = nullptr;                    // no es 0 ni NULL — con seguridad de tipos
enum class Color { Red, Green };      // con ámbito: Color::Red, sin int implícito
constexpr int kMax = 100;             // se calcula en tiempo de compilación

Etapa 2 — C++17: calidad de vida

6. Structured bindings

std::map<std::string, int> ages;
for (const auto& [name, age] : ages) {      // desempaqueta los pares directamente
    cout << name << " = " << age << '\n';
}

7. std::optional — «puede que haya un valor» en el tipo

std::optional<int> parse(std::string_view s);   // puede fallar

if (auto n = parse(input)) { use(*n); }      // sin centinela -1, sin parámetro de salida bool

Por qué: sustituye los valores de retorno mágicos y los parámetros de salida. Ahora el modo de fallo se ve en la firma.

8. std::string_view

void log(std::string_view msg);   // sin copia, funciona con literales y cadenas

Etapa 3 — C++20: el plato fuerte (donde lo «moderno» empieza de verdad)

9. Concepts — restricciones que el compilador entiende

template <typename T>
requires std::integral<T>
T twice(T x) { return x * 2; }

// los mensajes de error se vuelven humanos: «T no cumple integral»
// en lugar de páginas de ruido de instanciación de plantillas

Por qué: es la característica estrella de C++20. Convierte los errores de plantilla de algo ilegible en requisitos comprobables.

10. Ranges — pipelines en lugar de cuerpos de bucle

#include <ranges>

auto result = v
    | std::views::filter([](int x) { return x % 2 == 0; })
    | std::views::transform([](int x) { return x * x; })
    | std::views::take(5);          // perezoso: nada se ejecuta hasta que se itera

Por qué: se lee como el enunciado del problema. La evaluación perezosa no genera vectores temporales. Es el mayor cambio de estilo desde range-for.

11. Modules — reemplazan el «copia y pega» de #include

// math.cppm
export module math;
export int add(int a, int b) { return a + b; }

// main.cpp
import math;      // sin guardas de cabecera, sin reparsear el mundo entero

Por qué: compilaciones más rápidas y fronteras de módulo reales. En 2026, el soporte de las cadenas de herramientas sigue siendo desigual — conócelo, pero todavía no dependas de él en todas partes.

12. Corrutinas, std::format, span, consteval

std::cout << std::format("{} + {} = {}", a, b, a + b);   // printf con seguridad de tipos
void process(std::span<int> data);                       // vista de array, sin degradación a puntero
consteval int square(int x) { return x * x; }            // debe ejecutarse en tiempo de compilación

Etapa 4 — C++23 y más allá: lo que está llegando ahora

Cómo recorrer esto de verdad

  1. No lo leas en línea recta. Primero hazte con la Etapa 1 practicando: reescribe un bucle o una ordenación al estilo antiguo que ya hayas escrito.
  2. Compila con -std=c++20 -Wall (o c++23). La mitad del «C++ moderno» consiste simplemente en no escribir C++03.
  3. Una característica por problema de práctica. Nuestros 36 problemas están deliberadamente centrados en el núcleo de C++; reescribe uno usando std::vector + range-for + auto como ejercicio.
  4. Lee código real. Elige un proyecto C++ moderno de código abierto y busca con grep auto&, unique_ptr, std::ranges — fíjate en cómo los usan los proyectos reales.

Relacionado: tipos de datos, vector frente a array (EN), stack frente a heap (EN) y cómo conseguir un compilador de escritorio (EN).