# 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 <cstddef> // 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 <vector>

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<double> 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.
