Z dokumentacji wynika, że makra EXIT_* są zależne od implementacji, stąd wniosek że mogą istnieć platformy, dla których zerowy kod zwracany przez main niekoniecznie oznacza sukces. Zwracając jedno z takich makr masz większą pewność, co do rezultatu działania na jakichś egzotycznych platformach. W praktyce chyba nie spotkałem się z taką platformą, która zera nie traktowałaby jako EXIT_SUCCESS.
W C++ nie ma potrzeby jawnego pisania 'return 0' - przy wyjściu z main automatycznie jest zwracane zero.
Funkcja exit(int) kończy działanie programu z kodem, który podajesz jej jako argument. Niezalecana do użytku w C++, jako że nie wywołuje niektórych destruktorów.
exit() dla C: jak widać po przeczytaniu opisu, jest różnica, między return a exit. Przy exit() wywoływane są funkcje, zarejestrowane przez atexit() i... kilka innych rzeczy (patrz dokumentacja :).