Przyczyną problemów jest wskaźnik tab, a mianowicie:
1. W pierwszej petli for, w każdym przejściu pętli inkrementujesz ten wskaźnik. Następnie próbujesz zwolnić pamięć. Problem w tym, że zwalniasz nie tą pamięć, której żądałeś za pomocą operatora new. Wskaźnik tab przed pętlą, ma inną wartość, niż po wykonaniu pętli.
2. W drugie pętli for podobna sytuacja związana z inkrementacją wskaźnika. Z tą różnicą, że po wykonaniu pętli do funkcji dodaj() nie przekazujesz tablicy, którą zaalokowałeś wcześniej, tylko zawartość pamięci znajdującą się bezpośrednio za tablicą.
A żeby tego uniknąć, to możesz sobie zadeklarować pomocniczy wskaźnik na typ, do którego przypiszesz adres tablicy i będzie mógł z użyciem tego wskaźnika przesuwać się po kolejnych polach tablicy. Zawsze też będziesz mógł się odwołać do oryginalnego wskaźnika (nazwa tablicy). Inną opcją jest, użycie notacji ze wskaźnikiem:
for (int i=0;i<10;i++)
{
*(tab+i)=i;
cout<<"Adres pierwszej tablicy: "<<(int)(tab+i)<<endl;
cout<<"Wartosc pierwszej tablicy: "<<*(tab+i)<<endl;
}
Adres jaki przechowuje wskaźnik jest nieruszony, dostęp do kolejnych elementów jest możliwy dzięki zwiększaniu przesuniecia (zmienna i) względem początku tablicy. Na jedno wychodzi, tylko z tą różnicą, że nie zmienia się wartość wskaźnika.