Помоги мне изменить мой класс. Этот класс реализует работу с массивом в персистентном виде. Он хранит все версии в векторе (fat-node). Я хочу изменить подход к хранению данных  и использовать подход path-copying, чтобы те значения что повторяются в разных версиях лежали физически по одному адресу. Вот мой код:
#ifndef PERSISTENT_ARRAY_H
#define PERSISTENT_ARRAY_H

#include <vector>
#include <iostream>
#include <stack>
#include <tuple>


template <typename T>
class PersistentArray
{
private:
    std::vector<std::vector<T>> versions{}; // fat-node; all versions are stored here

    int current_version{};

public:
    // Constructor
    // takes an array and its size; 
    // creates vector from given array and pushes it as a base version
    PersistentArray(T* arr, int size)
    {
        std::vector<T> base(arr, arr + size); // transform array to vector
        versions.push_back(base); // save base version in the array of versions
        current_version = 0;
    }

    PersistentArray(std::vector<T> vec, int size)
    {
        auto base = vec; // transform array to vector
        versions.push_back(base); // save base version in the array of versions
        current_version = 0;
    }

    // Method to add a new version of array
    // takes an index of a version you want to change;
    // index of element to change and a new value
    //  
    void addVersion(int root_position, int change_index, T new_value)
    {
        // Error checking
        if (current_version < 0 || current_version >= versions.size() ||
            root_position < 0 || root_position >= versions.size() ||
            change_index < 0 || change_index >= versions[root_position].size())
        {
            throw std::out_of_range("Invalid root position");
        }

        auto temp = versions[root_position];
        temp[change_index] = new_value;
        versions.push_back(temp);
        current_version++;
    }

    // Method to make UNDO-action
    void undo()
    {
        if (current_version <= 0)
        {
            std::cout << "No actions to undo!" << std::endl;
            return;
        }

        current_version--;
        versions.push_back(versions[current_version]);
    }

    // Method to make REDO-action
    void redo()
    {
        if (current_version >= versions.size() - 1) {
            std::cout << "No actions to redo!" << std::endl;
            return;
        }

        current_version++;  // Переход к следующей версии
        versions.push_back(versions[current_version]);
    }

    // Method to print all versions
    void printAllVersions()
    {
        for (size_t i = 0; i < versions.size(); i++)
        {
            std::cout << "Version [" << i << "]: \t{";
            for (size_t j = 0; j < versions[i].size(); j++)
            {
                std::cout << versions[i][j] << " (" << &versions[i][j] << ")";
                if (j < versions[i].size() - 1)
                {
                    std::cout << ", ";
                }
            }
            std::cout << "}\n";
        }
    }

    const std::vector<T>& getVersion(size_t idx) const 
    {
        if (idx < versions.size()) 
        {
            return versions[idx];
        }
        throw std::out_of_range("Invalid version index");
    }
};


#endif // PERSISTENT_ARRAY_H


Пока все значения каждых версий - это совершенно разные объекты в памяти, несмотря на то что есть значения, которые одинаковы для разных версий:
Version [0]:    {100 (0x64feca46e700), 200 (0x64feca46e704), 300 (0x64feca46e708), 400 (0x64feca46e70c), 500 (0x64feca46e710)}
Version [1]:    {100 (0x64feca46e760), 200 (0x64feca46e764), -250 (0x64feca46e768), 400 (0x64feca46e76c), 500 (0x64feca46e770)}
Version [2]:    {100 (0x64feca46e6e0), 200 (0x64feca46e6e4), -250 (0x64feca46e6e8), -150 (0x64feca46e6ec), 500 (0x64feca46e6f0)}

Для изменения кода используй только умные указатели