🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Esercizi Gestione Memoria RAII C++

Codegrind Team•Jul 12 2024

Ecco degli esercizi semplici con soluzione per praticare la gestione della memoria con RAII (Resource Acquisition Is Initialization) in C++.

Esercizio 1: Gestione di risorse con std::unique_ptr

Usare `std::unique_ptr` per gestire l'allocazione e deallocazione dinamica della memoria.
#include <iostream>
#include <memory>

class Esempio {
public:
    Esempio() {
        std::cout << "Costruttore chiamato" << std::endl;
    }
    ~Esempio() {
        std::cout << "Distruttore chiamato" << std::endl;
    }
    void stampa() {
        std::cout << "Funzione stampa chiamata" << std::endl;
    }
};

int main() {
    std::unique_ptr<Esempio> ptr = std::make_unique<Esempio>();
    ptr->stampa();
    return 0;
}

Esercizio 2: Gestione di risorse con std::shared_ptr

Usare `std::shared_ptr` per gestire l'allocazione e deallocazione dinamica della memoria.
#include <iostream>
#include <memory>

class Esempio {
public:
    Esempio() {
        std::cout << "Costruttore chiamato" << std::endl;
    }
    ~Esempio() {
        std::cout << "Distruttore chiamato" << std::endl;
    }
    void stampa() {
        std::cout << "Funzione stampa chiamata" << std::endl;
    }
};

int main() {
    std::shared_ptr<Esempio> ptr1 = std::make_shared<Esempio>();
    {
        std::shared_ptr<Esempio> ptr2 = ptr1;
        ptr2->stampa();
    }
    std::cout << "Fuori dal blocco" << std::endl;
    return 0;
}

Esercizio 3: Gestione di file con RAII

Usare RAII per gestire l'apertura e la chiusura di un file.
#include <iostream>
#include <fstream>

class FileRAII {
private:
    std::ofstream file;
public:
    FileRAII(const std::string& filename) {
        file.open(filename);
        if (!file) {
            throw std::runtime_error("Impossibile aprire il file");
        }
    }
    ~FileRAII() {
        if (file.is_open()) {
            file.close();
            std::cout << "File chiuso" << std::endl;
        }
    }
    void scrivi(const std::string& contenuto) {
        file << contenuto << std::endl;
    }
};

int main() {
    try {
        FileRAII file("esempio.txt");
        file.scrivi("Ciao, mondo!");
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

Esercizio 4: Gestione di mutex con RAII

Usare RAII per gestire il locking e unlocking di un mutex.
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void stampa() {
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << "Thread ID: " << std::this_thread::get_id() << " sta eseguendo" << std::endl;
}

int main() {
    std::thread t1(stampa);
    std::thread t2(stampa);
    t1.join();
    t2.join();
    return 0;
}

Esercizio 5: Gestione di risorse con std::vector e std::unique_ptr

Usare `std::vector` e `std::unique_ptr` per gestire dinamicamente un array di oggetti.
#include <iostream>
#include <vector>
#include <memory>

class Esempio {
public:
    Esempio(int val) : valore(val) {
        std::cout << "Costruttore chiamato per " << valore << std::endl;
    }
    ~Esempio() {
        std::cout << "Distruttore chiamato per " << valore << std::endl;
    }
    void stampa() {
        std::cout << "Valore: " << valore << std::endl;
    }
private:
    int valore;
};

int main() {
    std::vector<std::unique_ptr<Esempio>> v;
    for (int i = 0; i < 5; ++i) {
        v.push_back(std::make_unique<Esempio>(i));
    }
    for (auto& e : v) {
        e->stampa();
    }
    return 0;
}

Esercizio 6: Gestione di un socket con RAII

Usare RAII per gestire l'apertura e chiusura di un socket.
#include <iostream>
#include <stdexcept>

class SocketRAII {
private:
    int socket;
public:
    SocketRAII(int s) : socket(s) {
        if (socket < 0) {
            throw std::runtime_error("Errore nell'apertura del socket");
        }
        std::cout << "Socket aperto" << std::endl;
    }
    ~SocketRAII() {
        if (socket >= 0) {
            // close(socket); // Usare la funzione appropriata per chiudere il socket
            std::cout << "Socket chiuso" << std::endl;
        }
    }
    void invia(const std::string& messaggio) {
        // send(socket, messaggio.c_str(), messaggio.size(), 0); // Usare la funzione appropriata per inviare dati
        std::cout << "Messaggio inviato: " << messaggio << std::endl;
    }
};

int main() {
    try {
        SocketRAII socket(1); // 1 è solo un esempio, usare il socket reale
        socket.invia("Ciao, mondo!");
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

Esercizio 7: Gestione di un database con RAII

Usare RAII per gestire l'apertura e chiusura di una connessione al database.
#include <iostream>
#include <stdexcept>

class DatabaseRAII {
private:
    // Simulazione di una connessione al database
    bool connected;
public:
    DatabaseRAII() {
        connected = true;
        std::cout << "Connessione al database aperta" << std::endl;
    }
    ~DatabaseRAII() {
        if (connected) {
            // chiudiConnessione(); // Usare la funzione appropriata per chiudere la connessione
            std::cout << "Connessione al database chiusa" << std::endl;
        }
    }
    void eseguiQuery(const std::string& query) {
        if (!connected) {
            throw std::runtime_error("Connessione al database non valida");
        }
        std::cout << "Query eseguita: " << query << std::endl;
    }
};

int main() {
    try {
        DatabaseRAII db;
        db.eseguiQuery("SELECT * FROM utenti");
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

Esercizio 8: Gestione di una classe custom con RAII

Creare una classe custom che gestisce risorse dinamiche con RAII.
#include <iostream>

class Risorsa {
public:
    Risorsa() {
        risorsa = new int(10);
        std::cout << "Risorsa alloc

ata" << std::endl;
    }
    ~Risorsa() {
        delete risorsa;
        std::cout << "Risorsa deallocata" << std::endl;
    }
    void stampa() {
        std::cout << "Valore della risorsa: " << *risorsa << std::endl;
    }
private:
    int* risorsa;
};

int main() {
    {
        Risorsa r;
        r.stampa();
    } // La risorsa viene deallocata automaticamente qui
    return 0;
}