Esercizi Regole 3-5 C++
- Rule of Three
- Esercizio 1: Implementazione della Rule of Three
- Esercizio 2: Profondo contro copia superficiale
- Rule of Five
- Esercizio 3: Implementazione della Rule of Five
- Esercizio 4: Utilizzo di std::move con la Rule of Five
- Esercizio 5: Creazione di un vettore di oggetti con la Rule of Five
- Esercizio 6: Gestione della memoria con la Rule of Five
- Esercizio 7: Creazione di una classe gestita con std::unique_ptr
- Esercizio 8: Creazione di una classe gestita con std::shared_ptr
Ecco degli esercizi con soluzione per praticare l’utilizzo delle Rule of Three e Rule of Five in C++.
Rule of Three
Esercizio 1: Implementazione della Rule of Three
Creare una classe con costruttore di copia, operatore di assegnazione di copia e distruttore.
#include <iostream>
class MyClass {private: int* data;public: // Costruttore MyClass(int value) : data(new int(value)) {}
// Costruttore di copia MyClass(const MyClass& other) : data(new int(*other.data)) { std::cout << "Costruttore di copia chiamato" << std::endl; }
// Operatore di assegnazione di copia MyClass& operator=(const MyClass& other) { if (this == &other) return *this; *data = *other.data; std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
// Distruttore ~MyClass() { delete data; std::cout << "Distruttore chiamato" << std::endl; }
void print() const { std::cout << "Valore: " << *data << std::endl; }};
int main() { MyClass obj1(10); MyClass obj2 = obj1; // Costruttore di copia chiamato obj2 = obj1; // Operatore di assegnazione di copia chiamato obj1.print(); obj2.print(); return 0;}
Esercizio 2: Profondo contro copia superficiale
Implementare una copia superficiale e osservare i problemi di gestione della memoria.
#include <iostream>
class MyClass {private: int* data;public: MyClass(int value) : data(new int(value)) {}
// Costruttore di copia (superficiale) MyClass(const MyClass& other) : data(other.data) { std::cout << "Costruttore di copia superficiale chiamato" << std::endl; }
// Distruttore ~MyClass() { delete data; std::cout << "Distruttore chiamato" << std::endl; }
void print() const { std::cout << "Valore: " << *data << std::endl; }};
int main() { MyClass obj1(10); MyClass obj2 = obj1; // Costruttore di copia superficiale chiamato obj1.print(); obj2.print(); return 0;}
Rule of Five
Esercizio 3: Implementazione della Rule of Five
Creare una classe con costruttore di copia, operatore di assegnazione di copia, costruttore di spostamento, operatore di assegnazione di spostamento e distruttore.
#include <iostream>
class MyClass {private: int* data;public: // Costruttore MyClass(int value) : data(new int(value)) {}
// Costruttore di copia MyClass(const MyClass& other) : data(new int(*other.data)) { std::cout << "Costruttore di copia chiamato" << std::endl; }
// Operatore di assegnazione di copia MyClass& operator=(const MyClass& other) { if (this == &other) return *this; *data = *other.data; std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
// Costruttore di spostamento MyClass(MyClass&& other) noexcept : data(other.data) { other.data = nullptr; std::cout << "Costruttore di spostamento chiamato" << std::endl; }
// Operatore di assegnazione di spostamento MyClass& operator=(MyClass&& other) noexcept { if (this == &other) return *this; delete data; data = other.data; other.data = nullptr; std::cout << "Operatore di assegnazione di spostamento chiamato" << std::endl; return *this; }
// Distruttore ~MyClass() { delete data; std::cout << "Distruttore chiamato" << std::endl; }
void print() const { if (data) std::cout << "Valore: " << *data << std::endl; else std::cout << "Nessun dato" << std::endl; }};
int main() { MyClass obj1(10); MyClass obj2 = std::move(obj1); // Costruttore di spostamento chiamato obj2.print(); obj1.print(); return 0;}
Esercizio 4: Utilizzo di std::move con la Rule of Five
Creare una classe con la Rule of Five e utilizzare `std::move` per spostare un oggetto.
#include <iostream>#include <utility> // Per std::move
class MyClass {private: int* data;public: MyClass(int value) : data(new int(value)) {}
MyClass(const MyClass& other) : data(new int(*other.data)) { std::cout << "Costruttore di copia chiamato" << std::endl; }
MyClass& operator=(const MyClass& other) { if (this == &other) return *this; *data = *other.data; std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
MyClass(MyClass&& other) noexcept : data(other.data) { other.data = nullptr; std::cout << "Costruttore di spostamento chiamato" << std::endl; }
MyClass& operator=(MyClass&& other) noexcept { if (this == &other) return *this; delete data; data = other.data; other.data = nullptr; std::cout << "Operatore di assegnazione di spostamento chiamato" << std::endl; return *this; }
~MyClass() { delete data; std::cout << "Distruttore chiamato" << std::endl; }
void print() const { if (data) std::cout << "Valore: " << *data << std::endl; else std::cout << "Nessun dato" << std::endl; }};
int main() { MyClass obj1(10); MyClass obj2 = std::move(obj1); // Costruttore di spostamento chiamato obj2.print(); obj1.print(); return 0;}
Esercizio 5: Creazione di un vettore di oggetti con la Rule of Five
Creare una classe con la Rule of Five e utilizzare un vettore per gestire piĂą oggetti.
#include <iostream>#include <vector>#include <utility>
class MyClass {private: int* data;public: MyClass(int value) : data(new int(value)) {}
MyClass(const MyClass& other) : data(new int(*other.data)) { std::cout << "Costruttore di copia chiamato" << std::endl; }
MyClass& operator=(const MyClass& other) { if (this == &other) return *this; *data = *other.data; std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
MyClass(MyClass&& other) noexcept : data(other.data) { other.data = nullptr; std::cout << "Costruttore di spostamento chiamato" << std::endl; }
MyClass& operator=(MyClass&& other)
noexcept { if (this == &other) return *this; delete data; data = other.data; other.data = nullptr; std::cout << "Operatore di assegnazione di spostamento chiamato" << std::endl; return *this; }
~MyClass() { delete data; std::cout << "Distruttore chiamato" << std::endl; }
void print() const { if (data) std::cout << "Valore: " << *data << std::endl; else std::cout << "Nessun dato" << std::endl; }};
int main() { std::vector<MyClass> vec; vec.push_back(MyClass(10)); vec.push_back(MyClass(20)); vec.push_back(MyClass(30));
for (const auto& obj : vec) { obj.print(); } return 0;}
Esercizio 6: Gestione della memoria con la Rule of Five
Creare una classe che gestisce un array dinamico e implementare la Rule of Five.
#include <iostream>#include <utility> // Per std::move
class MyArray {private: int* data; size_t size;public: MyArray(size_t size) : data(new int[size]), size(size) { for (size_t i = 0; i < size; ++i) { data[i] = static_cast<int>(i); } }
MyArray(const MyArray& other) : data(new int[other.size]), size(other.size) { std::copy(other.data, other.data + size, data); std::cout << "Costruttore di copia chiamato" << std::endl; }
MyArray& operator=(const MyArray& other) { if (this == &other) return *this; delete[] data; size = other.size; data = new int[size]; std::copy(other.data, other.data + size, data); std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
MyArray(MyArray&& other) noexcept : data(other.data), size(other.size) { other.data = nullptr; other.size = 0; std::cout << "Costruttore di spostamento chiamato" << std::endl; }
MyArray& operator=(MyArray&& other) noexcept { if (this == &other) return *this; delete[] data; data = other.data; size = other.size; other.data = nullptr; other.size = 0; std::cout << "Operatore di assegnazione di spostamento chiamato" << std::endl; return *this; }
~MyArray() { delete[] data; std::cout << "Distruttore chiamato" << std::endl; }
void print() const { for (size_t i = 0; i < size; ++i) { std::cout << data[i] << " "; } std::cout << std::endl; }};
int main() { MyArray arr1(10); MyArray arr2 = std::move(arr1); // Costruttore di spostamento chiamato arr2.print(); arr1.print(); // Non stampa nulla, arr1 è stato spostato
return 0;}
Esercizio 7: Creazione di una classe gestita con std::unique_ptr
Creare una classe che utilizza `std::unique_ptr` per gestire la memoria e implementare la Rule of Five.
#include <iostream>#include <memory>
class MyClass {private: std::unique_ptr<int> data;public: MyClass(int value) : data(std::make_unique<int>(value)) {}
MyClass(const MyClass& other) : data(std::make_unique<int>(*other.data)) { std::cout << "Costruttore di copia chiamato" << std::endl; }
MyClass& operator=(const MyClass& other) { if (this == &other) return *this; data = std::make_unique<int>(*other.data); std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
MyClass(MyClass&& other) noexcept : data(std::move(other.data)) { std::cout << "Costruttore di spostamento chiamato" << std::endl; }
MyClass& operator=(MyClass&& other) noexcept { if (this == &other) return *this; data = std::move(other.data); std::cout << "Operatore di assegnazione di spostamento chiamato" << std::endl; return *this; }
void print() const { if (data) std::cout << "Valore: " << *data << std::endl; else std::cout << "Nessun dato" << std::endl; }};
int main() { MyClass obj1(10); MyClass obj2 = std::move(obj1); // Costruttore di spostamento chiamato obj2.print(); obj1.print(); // Non stampa nulla, obj1 è stato spostato
return 0;}
Esercizio 8: Creazione di una classe gestita con std::shared_ptr
Creare una classe che utilizza `std::shared_ptr` per gestire la memoria e implementare la Rule of Five.
#include <iostream>#include <memory>
class MyClass {private: std::shared_ptr<int> data;public: MyClass(int value) : data(std::make_shared<int>(value)) {}
MyClass(const MyClass& other) : data(other.data) { std::cout << "Costruttore di copia chiamato" << std::endl; }
MyClass& operator=(const MyClass& other) { if (this == &other) return *this; data = other.data; std::cout << "Operatore di assegnazione di copia chiamato" << std::endl; return *this; }
MyClass(MyClass&& other) noexcept : data(std::move(other.data)) { std::cout << "Costruttore di spostamento chiamato" << std::endl; }
MyClass& operator=(MyClass&& other) noexcept { if (this == &other) return *this; data = std::move(other.data); std::cout << "Operatore di assegnazione di spostamento chiamato" << std::endl; return *this; }
void print() const { if (data) std::cout << "Valore: " << *data << std::endl; else std::cout << "Nessun dato" << std::endl; }};
int main() { MyClass obj1(10); MyClass obj2 = std::move(obj1); // Costruttore di spostamento chiamato obj2.print(); obj1.print(); // Non stampa nulla, obj1 è stato spostato
return 0;}