Wydaje mi się, że wiele większych bibliotek C ++ ostatecznie tworzy własny ciąg znaków. W kodzie klienta albo trzeba użyć jednego z biblioteki ( QString
, CString
, fbstring
itd, jestem pewien, że każdy może wymienić tylko kilka) lub zachować konwersji pomiędzy standardowym typu i jednym z zastosowań bibliotecznych (który większość czasu wiąże co najmniej jedna kopia).
A więc, czy jest w tym jakiś błąd lub coś złego std::string
(tak jak auto_ptr
semantyka była zła)? Czy zmieniło się to w C ++ 11?
java.lang.String
(brak przeciążenia operatora itp.) Sprawiłoby, że korzystanie z czegokolwiek innego byłoby utrudnieniem.Odpowiedzi:
Większość tych większych bibliotek C ++ została uruchomiona, zanim
std::string
została znormalizowana. Inne obejmują dodatkowe funkcje, które zostały znormalizowane późno lub nadal nie są znormalizowane, takie jak obsługa UTF-8 i konwersja między kodowaniami.Gdyby biblioteki te zostały zaimplementowane dzisiaj, prawdopodobnie wybraliby zapisywanie funkcji i iteratorów działających na
std::string
instancjach.źródło
char
jest wystarczająco duży, aby pomieścić dowolny punkt kodowy UTF-8. AFAIK, to jedyne „wsparcie”, które zapewnia C ++ 98.wchar_t
jest wystarczająco duże, aby reprezentować wszystkie punkty kodu Unicode. Co więcej, toczyła się cała dyskusja na temat UTF-16 uważanego za szkodliwy, gdy wysunięto bardzo przekonujący argument, że UTF-8 powinien być używany wyłącznie …String jest dużym zawstydzeniem dla C ++.
Przez pierwsze 15 lat w ogóle nie zapewniasz klasy ciągów - zmuszając każdy kompilator na każdej platformie i każdego użytkownika do tworzenia własnych.
Następnie tworzysz coś, co jest mylące, czy ma to być pełny interfejs API do manipulacji ciągami, czy tylko kontener znaków STL, z niektórymi algorytmami, które duplikują te na std :: Vector lub są różne.
W przypadku gdy oczywista operacja na łańcuchu, taka jak replace () lub mid (), wiąże się z takim bałaganem iteratorów, że musisz wprowadzić nowe słowo kluczowe „auto”, aby zachować dopasowanie instrukcji na jednej stronie i doprowadzić większość ludzi do rezygnacji z całego języka .
A potem masz unicode 'support' i std :: wstring, które jest po prostu arghh .....
<rant off> dziękuję - czuję się teraz znacznie lepiej.
źródło
std::string
. Brak klasy String w 1983 r. Nie usprawiedliwia posiadania ich więcej.Właściwie ... jest kilka problemów
std::string
i tak, w C ++ 11 jest trochę lepiej, ale nie wyprzedzajmy siebie.QString
iCString
są częścią starych bibliotek, dlatego istniały przed standaryzacją C ++ (podobnie jak SGI STL). Są więc musiał utworzyć klasę.fbstring
rozwiązać bardzo konkretne problemy dotyczące wydajności. Norma określa interfejs, a złożoność algorytmiczna gwarantuje minima, jednak szczegóły dotyczące jakości implementacji są takie, czy ostatecznie są szybkie, czy nie.fbstring
ma określone optymalizacje (find
na przykład związane z pamięcią masową lub szybsze ).Inne obawy, które nie zostały tutaj przywołane (en vrac):
std::string
koduje nieświadomy i nie ma specjalnego kodu dla UTF-8, łatwo jest przechowywać w nim ciąg UTF-8 i nieumyślnie go uszkodzićstd::string
interfejs jest rozdęty , wiele metod można było zaimplementować jako funkcje bezpłatne, a wiele z nich jest powielanych w celu dostosowania zarówno do interfejsu opartego na indeksie, jak i interfejsu opartego na iteratorze.źródło
c_str()
wskaźnik zwróci wskaźnik do ciągłej pamięci, co zapewnia pewną współdziałanie C. Nie można jednak modyfikować danych wskazanych. Typowe obejścia obejmują użycievector<char>
.&s[0]
, nie ma już znaczenia :)&s[0]
nie może wskazywać na łańcuch zakończony znakiem NUL (chybac_str()
że został wywołany od ostatniej modyfikacji).c_str()
Zwraca: Wskaźnikp
taki, żep + i == &operator[](i)
dla każdegoi
w[0,size()]
”.Oprócz wymienionych tutaj powodów istnieje jeszcze jedna - binarna kompatybilność . Autorzy bibliotek nie mają kontroli nad tym, jakiej
std::string
implementacji używasz i czy ma taki sam układ pamięci jak ich.std::string
jest szablonem, więc jego implementacja pochodzi z lokalnych nagłówków STL. Teraz wyobraź sobie, że używasz lokalnej wersji STL o zoptymalizowanej wydajności, w pełni zgodnej ze standardem. Na przykład, możesz zdecydować się na włożenie bufora statycznegostd::string
do każdego z nich, aby zmniejszyć liczbę alokacji dynamicznych i braków w pamięci podręcznej. W rezultacie układ pamięci i / lub rozmiar implementacji jest inny niż w bibliotece.Jeśli tylko układ jest inny, niektóre
std::string
wywołania funkcji składowych instancji przekazywane z biblioteki do klienta lub na odwrót mogą się nie powieść, w zależności od tego, które elementy zostały przeniesione.Jeśli rozmiar jest również inny, wszystkie typy bibliotek posiadające
std::string
element członkowski będą miały różny rozmiar po sprawdzeniu w bibliotece i kodzie klienta. Członkowie danych następujący postd::string
elemencie będą również przesunięciami przesunięcia, a każdy bezpośredni dostęp / dostęp wbudowany od klienta zwróci śmieci, pomimo „wyglądania OK” podczas debugowania samej biblioteki.Konkluzja - jeśli biblioteka i kod klienta zostaną skompilowane w różnych
std::string
wersjach, będą łączyły się dobrze, ale może to spowodować pewne nieprzyjemne, trudne do zrozumienia błędy. Jeśli zmieniszstd::string
implementację, wszystkie biblioteki ujawniające członków z STL muszą zostać ponownie skompilowane, aby pasowały dostd::string
układu klienta . A ponieważ programiści chcą, aby ich biblioteki były niezawodne, rzadko można je zobaczyć wstd::string
dowolnym miejscu.Szczerze mówiąc, dotyczy to wszystkich typów STL. IIRC nie mają znormalizowanego układu pamięci.
źródło
Istnieje wiele odpowiedzi na pytanie, ale oto kilka:
Dziedzictwo. Wiele bibliotek i klas ciągów zostało napisanych PRZED istnieniem std :: string.
Dla zgodności z kodem w C. Biblioteką std :: string jest C ++, ponieważ istnieją inne biblioteki łańcuchów, które działają z C i C ++.
Aby uniknąć alokacji dynamicznych. Biblioteka std :: string korzysta z alokacji dynamicznej i może nie być odpowiednia dla systemów osadzonych, kodu przerwań lub kodu w czasie rzeczywistym lub do funkcji niskiego poziomu.
Szablony Biblioteka std :: string oparta jest na szablonach. Do niedawna wiele kompilatorów C ++ miało słabo działającą lub nawet błędną obsługę szablonów. Niestety pracuję w branży, która korzysta z wielu niestandardowych narzędzi, a jeden z naszych łańcuchów narzędzi od dużego gracza w branży nie „oficjalnie” w 100% obsługuje C ++ (z błędami są szablony i in.).
Prawdopodobnie jest też wiele innych ważnych powodów.
źródło
Chodzi głównie o Unicode. Standardowa obsługa Unicode jest co najwyżej fatalna i każdy ma własne potrzeby w zakresie Unicode. Na przykład, ICU obsługuje wszystkie funkcje Unicode, jakie kiedykolwiek chciałeś, za najbardziej obrzydliwym interfejsem generowanym automatycznie z Java, jaki możesz sobie wyobrazić, a jeśli jesteś na Uniksie, że utkniesz z UTF-16, może nie być twoim pomysłem miło spędzony czas.
Ponadto wiele osób potrzebuje różnych poziomów obsługi Unicode - nie wszyscy potrzebują złożonych interfejsów API układu tekstu i tym podobnych rzeczy. Łatwo więc zrozumieć, dlaczego istnieje wiele klas ciągów - standardowa jest dość do kitu i wszyscy mają inne potrzeby niż nowe, nikt nie jest w stanie stworzyć jednej klasy, która może wykonywać wiele różnych platform obsługujących Unicode z przyjemnym interfejsem.
Moim zdaniem jest to głównie wina Komitetu C ++ za niepoprawne wsparcie dla Unicode - w 1998 lub 2003 roku, być może było to zrozumiałe, ale nie w C ++ 11. Mam nadzieję, że w C ++ 17 poradzą sobie lepiej.
źródło
Jest tak, ponieważ każdy programista ma coś do udowodnienia i odczuwa potrzebę stworzenia własnej niesamowitej, szybszej klasy ciągów dla swojej jednej, niesamowitej funkcji. Zazwyczaj jest to trochę zbyteczne i prowadzi do wszelkiego rodzaju dodatkowych konwersji ciągów z mojego doświadczenia.
źródło