Accessing vector at index 0 when it's empty

Viewed 622

Why I can still get the value from vectors[0] even I already pop_back() at the first step?
I'm guessing now my vectors is empty and check it by calling empty()

#include <iostream>
#include <vector>

struct Vector2 {
    int x, y;

    Vector2(int _x, int _y)
        : x(_x)
        , y(_y) {}

    Vector2(const Vector2& vec)
        : x(vec.x)
        , y(vec.y) {
        std::cout << "[Copy] Vector2{" << x << "," << y << "} copied!"
                  << std::endl;
    }

    void Print() {
        std::cout << "[Print] Vector2{" << x << "," << y << "}" << std::endl;
    }
};

void PrintVectors(const std::vector<Vector2>& vectors) {
    std::cout << "---" << std::endl;
    for (auto& vector : vectors) {
        std::cout << "Vector2{" << vector.x << "," << vector.y << "}"
                  << std::endl;
    }
}

int main() {
    std::vector<Vector2> vectors;
    vectors.push_back({21, 78});

    PrintVectors(vectors);

    // First
    vectors.pop_back();
    if (vectors.empty()) {
        std::cout << "Empty condition!" << std::endl;
    }
    vectors[0].Print(); // ---> I thought I'd get an error at this point.
    vectors.insert(vectors.begin(), {vectors[0].x + 1, vectors[0].y});
    PrintVectors(vectors);

    // Second
    vectors.pop_back();
    vectors[0].Print();
    vectors.insert(vectors.begin(), {vectors[0].x + 1, vectors[0].y});
    PrintVectors(vectors);

    // Third + no pop_back needed
    vectors[0].Print();
    vectors.insert(vectors.begin(), {vectors[0].x + 1, vectors[0].y});
    PrintVectors(vectors);

    // 4th
    vectors.pop_back();
    vectors[0].Print();
    vectors.insert(vectors.begin(), {vectors[0].x + 1, vectors[0].y});
    PrintVectors(vectors);
}

Then, this condition let me debugging through gdb. I see the value of _M_ is changing, but I have no clue what's going on (I can't see the pattern or relation between _M_start and _M_finish).

1 Answers

Accessing an empty vector at index 0 with operator[] is out of bounds and thus undefined behaviour and doing it renders your entire program invalid. The compiler is allowed to generate whatever result it wants. Any behaviour is acceptable. You cannot reason about programs containing UB.

Related