// Cuándo cambia de lugar el bloque de un std::vector.
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <vector>

// Guarda la dirección como número: un puntero al bloque anterior ya no se debe usar.
std::uintptr_t address_of(const std::vector<int>& v) {
    return reinterpret_cast<std::uintptr_t>(v.data());
}

void count_block_changes(std::vector<int>& v, int pushes) {
    int changes = 0;
    std::uintptr_t last = address_of(v);
    for (int i = 0; i < pushes; i++) {
        v.push_back(i);
        if (address_of(v) != last) {
            changes++;
            last = address_of(v);
        }
    }
    std::cout << pushes << " push_back: capacity " << v.capacity() << ", el bloque cambió " << changes
              << " veces\n";
}

int main() {
    std::vector<int> plain;
    count_block_changes(plain, 1000);

    std::vector<int> reserved;
    reserved.reserve(1000);
    count_block_changes(reserved, 1000);

    // Un índice sigue siendo válido después de crecer: se vuelve a calcular la posición.
    std::vector<int> grades = {10, 20};
    std::size_t first = 0;
    for (int i = 0; i < 100; i++) {
        grades.push_back(i);
    }
    std::cout << "grades[first] = " << grades[first] << "\n";
    return 0;
}
