Don't confuse the location where the vector object is stored with the location where it stores its elements. Internally the vector contains a pointer to an array of elements.
What confuses me is that &v[0] remains the same during the code runs.
v[0] is a std::vector<int>. Inserting new elements to that vector might affect the location of its elements but not of the vector object itself.
If you instead call push_back on v then you'll see that &v[0] and &v[1] changes (assuming a "reallocation" happens).
what is the meaning of &v and &v[0] which are different? &v[0] is also different from &v[0][0] which is the address of v[0][0].
v is the vector<vector<int>> object.
v[0] and v[1] are the vector<int> objects stored as elements in v.
v[0][0] is the first element of v[0].
Using & in front of an object gives you the memory address (pointer) of that object.
Last but not least, why are &v[0][0] and &v[0][1] contigous while &v[0] and &v[1] seem not?
v[0][0] and v[0][1] belong to the same vector v[0] so they should be stored contiguously (after each other) in memory.
The same should be true about v[0] and v[1]. They both belong to v.
When push_back() executed, the vector will be reallocated.
No, the vectors may be reallocated. Both v[0] and v[1], but not v. I say "may", because the std::vector constructor only guarantees that the capacity will be >= the requested size.
What confuses me is that &v[0] remains the same during the code runs.
Yes, because v is not reallocated. Check &v[0][0] and &v[1][0].
Further, what is the meaning of &v and &v[0] which are different? &v[0] is also different from &v[0][0] which is the address of v[0][0].
&v is the address of the top-level vector v. &v[0] is the address of the first element of v, which is also a vector. &v[0][0] is the address of the first element of the first element (this is not a typo) of v, which is an int.
Last but not least, why are &v[0][0] and &v[0][1] contigous while &v[0] and &v[1] seem not?
v[0] and v[1] are contiguous. What's happening is that sizeof(std::vector<int>) is larger than you're expecting. Try this:
1 2 3 4 5 6 7 8 9
auto a = (uintptr_t)&v[0];
auto b = (uintptr_t)&v[1];
auto c = sizeof(std::vector<int>);
std::cout << c << std::endl;
std::cout << b - a << std::endl;
if (b - a == c)
std::cout << "They're contiguous!\n";
else
std::cout << "They're not contiguous!\n";