The following line doesn't do what you think:
arr[i]=inp;
Here you are assigning to arr[i] a pointer to inp, not copying the input buffer into arr[i]. During the same iteration (i.e. at the first cout << arr[i]) everything is fine. As soon as you overwrite the contents of inp, the changes will reflect in all the cells of arr you have assigned to that same pointer. In fact, at the end of the loop all cells of arr point to inp, which means you will always see the last value extracted from cin.
As a solution, make arr an array of "strings" and copy the input buffer using strncpy:
char arr[2][20];
int i=0;
char inp[20];
while(i<2)
{
cin>>inp;
strncpy(arr[i], inp, 20);
cout<<arr[i]<<endl;
i++;
}
cout<<arr[0]<<endl;
cout<<arr[1]<<endl;
Or use C++ std::string if possible.
std::array- are very valid in many cases. Sure, for ad-hoc dynamic arrays like this seems to be,vectoris better, but on a general level - as you've phrased it - I don't agree with either of the blanket recommendations you're making.