Why does the last expected output differ from the actual output in the following code?
#include<iostream>
#include<fstream>
#include<istream>
#include<sstream>
#include<vector>
using namespace std;
int main()
{
vector<int> v;
for(int ii = 0; ii < 4; ii++){
v.push_back(0);
}
vector<vector<int>> twoDv;
for(int ii = 0; ii < 5; ii++){
twoDv.push_back(v);
}
cout<<"Expected Output : " << &twoDv[0][0] <<'\t'<< (&twoDv[0][0] + 3) <<'\t'<< (&twoDv[0][3] + 1)<<'\n';
cout<<"Actual Output : " << &twoDv[0][0] <<'\t'<< &twoDv[0][3] <<'\t'<< &twoDv[1][0] << '\n';
}
The standard doesn't say that &twoDv[1][0]
is equal to &twoDv[0][3] + 1
. It says that &twoDv[1]
is equal to &twoDv[0] + 1
, and that &twoDv[0][1]
is equal to &twoDv[0][0] + 1
.
Suppose for a moment that &twoDv[1][0]
were equal to &twoDv[0][3] + 1
, and then you did twoDv[0].resize(5);
. Suddenly we have a conflict, &twoDv[0][3] + 1
can't be the address of &twoDv[1][0]
and also the address of &twoDv[0][4]
. So the resize operation on twoDv[0]
would have to invalidate iterators and references to the elements of another vector twoDv[1]
. This would be very undesirable behavior.
vector< vector< int > >
is not a two-dimensional array like int[5][5]
. It's an array of pointers to arrays. (To be more precise, it contains a sequence of std::vector
objects containing pointers to integers.) Only the "rows" are contiguous. Different rows are not contiguous with each other because they may be stored in different malloc'ed blocks of memory.
A vector
does store its elements in continuous memory. But the elements of vector<vector<int>> twoDv;
are vectors, not ints, and the ints are stored in continuous memory internally, per vector.
Think of an array of pointers:
int* x[10];
The 10
pointers are stored in continuous memory, but what they point to doesn't have to be in continuous memory.