Zacznijmy od tego że const char * jest to literał znakowy (string z języka C). Raz zadeklarowany string w ten sposób jest nie zmienny.
const char * a="ala ma kota";
cout<<a[0]; //OK
a[0]='A'; //Nie ok
Pragnę zwrócić uwagę że do elementów można dostać się jak by to była tablica znaków. Możesz wypisać element o indexie 0 zaś zmienić elementu pod żadnym z indexów nie wolno.
Każdy napis zgodny z standardem języka C musi mieć na końcu znak końca napisu tak zwany NULL zwany inaczej \0.
Weźmy teraz ten sam przypadek co poprzednio ale dla tablicy znaków.
char b[12]="ala ma kota"; // rozmiar tablicy to długość napisu +1
cout<<b[0];//OK
b[0]='A';//OK
Deklarujemy tablicę która będzie zawierać nasz napis. Zwróć uwagę że rozmiar tablicy to 12 elementów, napis "Ala ma kota" ma długość 11. Dzieję się tak dlatego że każdy poprawny napis w języku C musi zawierać znak końca napisu, wspomniany NULL, stawiamy go na końcu dlatego jest plus jedna komórka.
std::string to nic innego jak połączenie tych dwóch koncepcji plus świata obiektowego. Jest to klasa należąca do standardowej przestrzeni nazw, została wprowadzona w języku C++. Klasa ta pozwala w łatwy sposób operować na napisach, ma przeciążone operatory [] dlatego pozwala odwoływać się do stworzonego obiektu jak by to była tablica. Dodatkowo umożliwia konkatenację stringów (łączenie) za pomocą operatora + oraz +=. Przeciążone zostąły również operatory << jak i >> co pozwala na łatwe wprowadzanie danych jak i wypisywanie zawartości stringa na ekran.
std::string a="Ala ma kota";
cout<<a.size()<<endl; //wypisuje długość napisu
cout<<a<<endl;//wypisuje napis;
cout<<a[0]<<endl;//wypisuje element o indexie 0
a[0]='A';//zmienia element o indexie 0
Klasa string posiada wiele metod, między innym metodę size która zwraca długość napisu. Ciekawostką jest że ze względów historycznych klasa string posiada zarówno metodę size jak i length, obydwie zwracają długość napisu.
Polecam zapoznać się z dokumentacją klasy:
https://en.cppreference.com/w/cpp/string/basic_string