std::string
nie waży 4 bajtów (chyba, że masz architekturę z 2-bajtowym wskaźnikiem). Minimalna implementacja musi mieć minimum wielkość 2 wskaźników, ale nie to jest powodem. Każda kopia wymaga alokacji dla nowego stringa, a następnie skopiowania jego zawartości. Tzw. Copy-On-Write nie jest zgodne ze standardem C++11 (wcześniej niektóre implementacje tego używały). Wobec tego jeśli tylko danego stringa czytasz, to lepiej wziąć do niego const referencję - unikasz wtedy niepotrzebnego kopiowania.
Przy okazji, w C++11 pojawił się nowy idiom - jeśli kopiowanie jest nieuniknione, np. funkcja jest setterem w klasie, albo będziesz chciał swoją kopię modyfikować, wtedy lepiej przyjąć w parametrze kopię, dzięki czemu możesz użyć przenoszenia, np. w takiej sytuacji:
void set(string x){
y = move(x);
}
dzięki czemu następujące wywołanie odbyłoby się bez żadnej kopii, co przy const referencji nie byłoby możliwe.
set("foo");
Minusem jest dodatkowa operacja przenoszenia w pozostałych przypadkach, ale z reguły przenoszenie jest prawie darmowe (pomijając POD)