std::string_view
jest szybszy w kilku przypadkach.
Po pierwsze, std::string const&
wymaga , aby dane znajdowały się w std::string
, a nie w surowej tablicy C, char const*
zwróconej przez C API, std::vector<char>
wytworzonej przez jakiś silnik deserializacji itp. Unikana konwersja formatu pozwala uniknąć kopiowania bajtów i (jeśli łańcuch jest dłuższy niż SBO¹ dla konkretnej std::string
implementacji) unika alokacji pamięci.
void foo( std::string_view bob ) {
std::cout << bob << "\n";
}
int main(int argc, char const*const* argv) {
foo( "This is a string long enough to avoid the std::string SBO" );
if (argc > 1)
foo( argv[1] );
}
W tej string_view
sprawie nie dokonuje się żadnych alokacji , ale byłoby, gdyby foo
wziął std::string const&
zamiast zamiast string_view
.
Drugim naprawdę ważnym powodem jest to, że pozwala na pracę z podciągami bez kopii. Załóżmy, że analizujesz 2-gigabajtowy ciąg Json (!) ². Jeśli go parsujesz std::string
, każdy taki parsowany węzeł, w którym przechowują nazwę lub wartość węzła, kopiuje oryginalne dane z ciągu 2 gb do węzła lokalnego.
Zamiast tego, jeśli parsujesz to do std::string_view
s, węzły odnoszą się do oryginalnych danych. Pozwala to zaoszczędzić miliony przydziałów i zmniejszyć o połowę wymagania dotyczące pamięci podczas analizowania.
Przyspieszenie, które można uzyskać, jest po prostu śmieszne.
Jest to skrajny przypadek, ale inne przypadki „zdobycia podciągu i pracy z nim” również mogą generować przyzwoite przyspieszenia string_view
.
Ważną częścią decyzji jest to, co tracisz, używając std::string_view
. To niewiele, ale to jest coś.
Tracisz domniemane zerowe zakończenie i to wszystko. Więc jeśli ten sam ciąg zostanie przekazany do 3 funkcji, z których każda wymaga zerowego terminatora, konwersja na std::string
jeden raz może być mądra. Zatem jeśli wiadomo, że twój kod potrzebuje terminatora zerowego i nie oczekujesz ciągów zasilanych z buforów typu C lub podobnych, może weź std::string const&
. W przeciwnym razie weź std::string_view
.
Gdyby std::string_view
flaga oznaczała, że jeśli jest zerowa (lub coś bardziej wymyślnego), usunęłaby nawet ten ostatni powód, aby użyć std::string const&
.
Zdarzają się przypadki, w których wzięcie „ std::string
nie” const&
jest optymalne w stosunku do std::string_view
. Jeśli po wywołaniu musisz posiadać kopię łańcucha na czas nieokreślony, efektywne jest przyjmowanie wartości według. Będziesz albo w przypadku SBO (bez przydziałów, wystarczy kilka kopii znaków, aby go zduplikować), albo będziesz mógł przenieść bufor przydzielony na stos do lokalnego std::string
. Posiadanie dwóch przeciążeń std::string&&
i std::string_view
może być szybciej, ale tylko nieznacznie, a to spowodowałoby kodu skromną uwędzić (który może kosztować wszystkie zyski prędkość).
¹ Optymalizacja małego bufora
² Rzeczywisty przypadek użycia.
std::string_view
jest tylko abstrakcją pary (char * begin, char * end). Używasz go, gdy robieniestd::string
byłby niepotrzebną kopią.