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::stringimplementacji) 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_viewsprawie nie dokonuje się żadnych alokacji , ale byłoby, gdyby foowziął 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_views, 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::stringjeden 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_viewflaga 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::stringnie” 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_viewmoż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_viewjest tylko abstrakcją pary (char * begin, char * end). Używasz go, gdy robieniestd::stringbyłby niepotrzebną kopią.