Programación C++ – Optimización de código

En C++, cuando hablamos de optimización de código, estamos hablando de hacer que tus programas sean más eficientes y corran mejor. Se trata de reducir el uso de recursos y el tiempo que lleva ejecutarlos. Aunque es importante tener en cuenta que no siempre hay que volverse loco optimizando desde el principio, porque eso puede hacer que el código sea un enredo y difícil de mantener. Por lo general, lo mejor es seguir prácticas de programación sólidas y dejar la optimización para cuando de verdad sea necesaria. Aquí te damos algunas estrategias y tips para que tu código en C++ tenga mejor rendimiento:

Ejemplo 1: Uso Eficiente de Contenedores:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numeros;
    
    for (int i = 0; i < 1000000; ++i) {
        numeros.push_back(i);
    }

    return 0;
}

Optimización: En lugar de usar std::vector, que realiza realocaciones a medida que crece, podemos usar std::vector::reserve para preasignar la memoria necesaria antes de agregar elementos. Esto reduce las realocaciones y mejora el rendimiento.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numeros;
    numeros.reserve(1000000);
    
    for (int i = 0; i < 1000000; ++i) {
        numeros.push_back(i);
    }

    return 0;
}

Ejemplo 2: Minimizar el Uso de Objetos Temporales:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numeros = {5, 2, 8, 1, 9, 3};

    int suma = 0;
    for (int num : numeros) {
        suma += num;
    }

    std::cout << "Suma: " << suma << std::endl;

    return 0;
}

Optimización: En lugar de usar un bucle for que itera sobre copias de los elementos del vector, podemos usar una referencia constante para evitar copias innecesarias y mejorar la eficiencia.

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numeros = {5, 2, 8, 1, 9, 3};

    int suma = 0;
    for (const int& num : numeros) {
        suma += num;
    }

    std::cout << "Suma: " << suma << std::endl;

    return 0;
}

Ejemplo 3: Elección de Algoritmo Eficiente:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numeros = {5, 2, 8, 1, 9, 3};

    // Encontrar el mínimo valor utilizando un bucle
    int min_valor = numeros[0];
    for (int num : numeros) {
        if (num < min_valor) {
            min_valor = num;
        }
    }

    std::cout << "Mínimo valor: " << min_valor << std::endl;

    return 0;
}

Optimización: En lugar de usar un bucle para encontrar el mínimo valor, podemos usar la función std::min_element de la STL, que realiza la búsqueda de manera más eficiente.

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numeros = {5, 2, 8, 1, 9, 3};

    auto min_it = std::min_element(numeros.begin(), numeros.end());
    std::cout << "Mínimo valor: " << *min_it << std::endl;

    return 0;
}

Ejemplo 4: Uso de Prefijos y Unarios:

#include <iostream>

int main() {
    int contador = 0;

    // Ineficiente: contador = contador + 1;
    // Eficiente: contador += 1; o ++contador;
    
    return 0;
}

Optimización: En lugar de utilizar la expresión contador = contador + 1;, puedes emplear las formas más eficientes contador += 1; o ++contador; para incrementar el valor del contador.

Código Sin Optimizar:

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int a = 5, b = 10, c = 15;
    
    // Declaraciones poco descriptivas
    vector<int> v;
    int arr[10];
    
    // Bucle for ineficiente
    for (int i = 0; i < 10; i++) {
        v.push_back(i);
    }
    
    // Bucle while ineficiente
    int i = 0;
    while (i < v.size()) {
        cout << v[i] << " ";
        i++;
    }
    
    // Uso de operadores lógicos innecesarios
    if (a != 5 && b == 10 && c >= 15) {
        cout << "Condición verdadera" << endl;
    }
    
    // Uso excesivo de variables temporales
    int suma = a + b;
    int producto = a * b;
    int resultado = suma + producto;
    
    // Falta de comentarios y explicaciones
    if (resultado > 100) {
        cout << "Resultado grande" << endl;
    }
    
    return 0;
}

Código Optimizado:

#include <iostream>
#include <vector>

using namespace std;

int main() {
    const int numElements = 10;
    
    // Declaraciones más descriptivas
    vector<int> numeros;
    int arreglo[numElements];
    
    // Bucle for más eficiente
    for (int i = 0; i < numElements; ++i) {
        numeros.push_back(i);
    }
    
    // Bucle for-each (rango) más eficiente
    for (int num : numeros) {
        cout << num << " ";
    }
    
    // Uso de operadores lógicos simplificados
    if (a == 5 && b == 10 && c == 15) {
        cout << "Condición verdadera" << endl;
    }
    
    // Uso directo de operaciones sin variables temporales innecesarias
    int resultado = a + b + a * b;
    
    // Comentario explicativo
    if (resultado > 100) {
        cout << "Resultado grande" << endl;
    }
    
    return 0;
}

En este código optimizado, se han aplicado todas las optimizaciones previamente discutidas para mejorar la legibilidad y la eficiencia del código. Las variables tienen nombres más descriptivos, los bucles son más eficientes, se usan operadores lógicos de manera simplificada y se eliminan variables temporales innecesarias. Además, se ha añadido un comentario explicativo para aumentar la comprensión del código.

Es súper importante balancear entre hacer que todo funcione súper rápido y que el código se pueda entender fácil. No te pases tratando de hacerlo ultra rápido y complicado, a menos que sea mega necesario. En un montón de situaciones, el programa mismo se encargará de hacerlo más rápido sin que hagas nada, así que es mejor concentrarse en escribir código que cualquiera pueda leer y entender en lugar de tratar de hacerlo ultra eficiente desde el principio. ¡La clave está en el equilibrio, amigo!

Pueder ir al artículo principal:

Códigos Sencillos hechos en C++

Deja un comentario