Files
Code/cplusplus/geminitutorial/tutorial2/tutorial-2.1-plan.md
2026-01-06 15:05:27 +00:00

4.6 KiB

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

#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

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