#include <iostream>
using namespace std;

int main(){
  
  int i = 5, j = 7, k = 9;
  
  // creo una variabile puntatore che dovra' contenere l'indirizzo 
  // di un'altra variabile puntatore allocata sullo heap
  int** p = new int*;
  
  
  *p = &i;  // faccio in modo che la variabile puntatore allocata sullo heap
            // punti alla variabile intera i
  
  cout << (*(*p))<<endl;  // stampa 5, ossia il contenuto di i

  *p = &j;
  cout << (*(*p))<<endl;  // stampa 7, ossia il contenuto di j
  
  cout << endl;
  
  // creo un vettore di tre puntatori ad intero
  int **q = new int*[3];
  q[0] = &i;  // equivalente a *(q+0) = &i;
  q[1] = &j;  // equivalente a *(q+1) = &j;
  q[2] = &k;  // equivalente a *(q+2) = &k;
  
  
  cout<< *(q[0])<<endl; // 5   (equivale a q[0][0])
  cout<< *(q[1])<<endl; // 7   (equivale a q[1][0])
  cout<< *(q[2])<<endl; // 9   (equivale a q[2][0])
  
  cout << endl;
  
  cout<< "stampo a video il contenuto delle variabili puntate mediante doppio indice"<<endl;  
  cout<< q[0][0]<<endl; // 5
  cout<< q[1][0]<<endl; // 7 
  cout<< q[2][0]<<endl; // 9
  
  // dealloco il vettore di tre puntatori ad intero
  delete[] q;
    
  
  cout << endl; 
  
  // creo un nuovo vettore di vettori, allocato sullo heap
  int **r = new int*[4];
  
  
  // alloco i singoli vettori (si noti che i singoli vettori hanno lunghezza diversa)  
  r[0] = new int[1]; // r[0] -> [ ]
  r[1] = new int[2]; // r[1] -> [ | ]
  r[2] = new int[3]; // r[2] -> [ | | ]
  r[3] = new int[4]; // r[3] -> [ | | | ]
  
  for (int i = 0; i < 4; i++)
	  for (int j = 0; j <= i; j++)
	     r[i][j] = i + j;
	
	
  // r[0] -> [0]
  // r[1] -> [1|2]
  // r[2] -> [2|3|4]
  // r[3] -> [3|4|5|6]

    	 
  for (int i = 0; i < 4; i++){
	  for (int j = 0; j <= i; j++)
	     cout << r[i][j]<<' ';
	  cout << endl;
  }
	 
  // deallocazione dei singoli vettori
  delete[] r[0];
  delete[] r[1];
  delete[] r[2];
  delete[] r[3];
  
  // deallocazione del vettore di puntatori a intero
  delete[] r;
	 
  return 0;
  
  
}