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;
}