Hello, could someone explain me why this two codes work? I got surprised when I found out that I can use either push_back() method or direct access mtr[i][j] when mtr was declared as: vector< vector<double> > mtr;

which of the codes would be the most efficient?

code 1:
Code:
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  int length = 5;
  int num = 10;
  
  vector< vector<int> > mtr;
  
  mtr.resize(length);
  for(int i = 0; i < length; i++)
  {
    mtr[i].reserve(length);

    for (int j = 0; j < length; j++)
    {
      mtr[i][j] = num;
      cout<<"mtr["<<i<< "]["<< j<< "]= "<< mtr[i][j] <<endl;
    }
  }  
    
  return 0;
}
code 2:
Code:
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  int length = 5;
  int num = 10;
  
  vector< vector<int> > mtr;
  
  mtr.resize(length);
  for(int i = 0; i < length; i++)
  {
    mtr[i].reserve(length);

    for (int j = 0; j < length; j++)
    {
      mtr[i].push_back(num);
      cout<<"mtr["<<i<< "]["<< j<< "]= "<< mtr[i][j] <<endl;
    }
  }  
    
  return 0;
}