Jak deklarować funkcje z parametrem std::string?

0

Witam, często przeglądając dokumentację różnego typu bibliotek (np Qt) napotykam się z zapisem:

void funkcja(const std::string & s);

Moje pytanie brzmi: jaki sens ma deklarowanie parametru 's' jako stałą referencję? Przecież zmienna string waży 4 bajty, tyle samo co referencja, więc jaki mamy z tego zysk? Dlaczego się tak robi? Jestem bardzo ciekawy :)

0

Aha takie coś, czyli dobrze rozumiem za pomocą stałej referencji jest wykonywana głęboka kopia obiektu string tak?:)

1

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)

0

Żeby nie tracić na kopiach, parametry „klasowe” powinno się przekazywać przez stałą referencję a nie przez wartość:

void funkcja(const std::string &s);

Spokojnie natomiast można zwracać z funkcji obiekt klasy przez wartość, i jest to zalecana forma:

std::string funkcja();

kompilator zoptymalizuje kod tak by uniknąć niepotrzebnych kopii.
Zamiast zwracać wartości można oczywiście podawać parametr jako zwykłą referencję,

void funkcja(std::string &s);

ale wtedy przestaje być czytelne, czy ten parametr jest wyjściowy, wejściowo-wyjściowy, czy tylko wejściowy ale ktoś zapomniał consta.

0

Tak w woli ścisłości chciałbym dopytać, czy tego typu przekazywanie parametru, tyczy się tylko klasy string, czy wszystkich klas, w których jest to możliwe?

0

Dla wszystkich, poza typami wbudowanymi, chociaż często kompilator jest w stanie to zoptmalizować i dla nich.

1 użytkowników online, w tym zalogowanych: 0, gości: 1