# Tutorial 2.1 Plan: Resource Management & The Rule of Zero **Objective:** To master modern C++ resource management techniques, moving away from manual memory handling (`new`/`delete`) to the robust RAII (Resource Acquisition Is Initialization) idiom. This tutorial will demonstrate the "Rule of Zero" by refactoring a C++98-style class that requires manual memory management into a modern, safer equivalent using standard library containers and smart pointers. --- ## 1. Project Setup To keep our tutorials organized, we will create a new directory for this lesson. 1. **Create a `tutorial-2` directory:** Inside the `GeminiTutorial` project root. 2. **Copy Configuration:** Copy the `CMakeLists.txt` and the `.vscode` directory from `tutorial-1` into the new `tutorial-2` directory. This preserves our build and debug configurations. 3. **Update `CMakeLists.txt`:** Modify the `project()` name at the top of `tutorial-2/CMakeLists.txt` from `Tutorial1` to `Tutorial2`. --- ## 2. The "Old Way": Manual Memory Management (The Rule of Three/Five) First, we'll create a class that manually manages a dynamic array of doubles. This will highlight the complexity and risks of the C++98 approach. **File:** `tutorial-2/src/StockData_Old.h` ```cpp #pragma once // Use modern include guard #include // For size_t class StockData_Old { public: // Constructor StockData_Old(size_t size); // Copy Constructor (Rule 1 of 3) StockData_Old(const StockData_Old& other); // Copy Assignment Operator (Rule 2 of 3) StockData_Old& operator=(const StockData_Old& other); // Destructor (Rule 3 of 3) ~StockData_Old(); // Public method to access data double& at(size_t index); private: double* data_; size_t size_; }; ``` We will also create the corresponding `.cpp` file to implement these special member functions, demonstrating the need for deep copies and manual cleanup. --- ## 3. The "Modern Way": Automatic Resource Management (The Rule of Zero) Next, we will create a modern equivalent that leverages `std::vector`. This class will achieve the same functionality with significantly less code and greater safety. **File:** `tutorial-2/src/StockData_Modern.h` ```cpp #pragma once #include class StockData_Modern { public: // Constructor StockData_Modern(size_t size); // No Copy Constructor, Copy Assignment, or Destructor needed! // The compiler-generated versions work perfectly because `std::vector` handles itself. // Public method to access data double& at(size_t index); private: std::vector data_; }; ``` This class adheres to the **Rule of Zero**, as it owns its resources through a standard library container and requires no custom resource management code. --- ## 4. Introducing Smart Pointers for Single Object Ownership While containers are for sequences of objects, smart pointers manage the lifetime of a single dynamically allocated object. 1. **`std::unique_ptr`:** Represents exclusive ownership. The object is destroyed automatically when the `unique_ptr` goes out of scope. 2. **`std::shared_ptr`:** Represents shared ownership. The object is destroyed only when the last `shared_ptr` pointing to it is destroyed. We will create a simple `Trade` class and a `main.cpp` to demonstrate creating and managing `Trade` objects on the heap using both `std::unique_ptr` and `std::shared_ptr`. --- ## 5. Updating the Build System and Main Application We will modify `tutorial-2/CMakeLists.txt` to include all our new source files (`.cpp` files for `StockData_Old`, `StockData_Modern`, and the new `main.cpp`). The `main.cpp` will first use `StockData_Old` to illustrate its usage (and potential pitfalls), then use `StockData_Modern` to show the simplicity and safety of the modern approach, and finally demonstrate the usage of smart pointers. --- ## 6. Summary and Key Takeaways This tutorial will provide hands-on experience with the core principles of modern C++ resource management: * **RAII:** Let objects manage resources. Acquisition is in the constructor, release is in the destructor. * **Rule of Zero:** By using standard library classes like `std::vector`, `std::string`, `std::unique_ptr`, and `std::shared_ptr` to handle resource ownership, your own classes often don't need any custom destructor, copy/move constructors, or assignment operators. * **Expressing Ownership:** Choose the right tool for the job: * `std::vector` for owning a dynamic array of elements. * `std::unique_ptr` for exclusive ownership of a single heap-allocated object. * `std::shared_ptr` for shared ownership of a single heap-allocated object.