Questo:
istream & operator >> (istream & in, Punto &a) {
nodo* pc=a.p;
cout << "Inserisci valore x: ";
in >> pc->val1;
cout << "Inserisci valore y: ";
in >> pc->val2;
a.push(pc->val1,pc->val2);
return in;
}
è errato. Chiedi un nodo alla lista, assegni dati a sto nodo (senza controllare se esiste) e infine allocchi un altro nodo con gli stessi dati. Si può capire cosa stai cercando di fare?
Poi qui:
friend ostream & operator << (ostream & os, Punto a);
perché passi per valore invece che per riferimento costante?
friend ostream & operator << (ostream & os, const Punto & a);