Dokumentacja jest poprawna. Użyj, c_str()
jeśli chcesz łańcuch zakończony wartością null.
Jeśli realizatorzy wydarzyło wdrożyć data()
w kategoriach c_str()
nie trzeba się martwić, nadal używać data()
, jeśli nie trzeba ciąg być zerowa zakończone w pewnym realizacji może okazać się skuteczniejsze niż c_str ().
łańcuchy niekoniecznie muszą składać się z danych znakowych, mogą składać się z elementów dowolnego typu. W takich przypadkach data()
ma to większe znaczenie. c_str()
moim zdaniem jest naprawdę przydatne tylko wtedy, gdy elementy twojego ciągu są oparte na znakach.
Dodatkowo : od C ++ 11 obie funkcje muszą być takie same. tj. data
musi być teraz zakończony wartością zerową. Zgodnie z cppreference : " Zwracana tablica jest zakończona znakiem null, to znaczy data () i c_str () pełnią tę samą funkcję."
.data()
inne niż stałe dla , więc nie są one już równoważne dla niestałych ciągów.W C ++ 11 / C ++ 0x ,
data()
ic_str()
nie jest już inna. W związku z tymdata()
wymagane jest również zerowe zakończenie na końcu.źródło
std::string
przydzielenia dodatkowegochar
dla końcowego'\0'
. Kiedy to zrobiszstd::string s("\0");
, obie wartościs.data()[0]
is.data()[1]
zostaną ocenione na 0.Nawet wiedząc, że widzieliście, że robią to samo lub że .data () wywołuje .c_str (), nie jest poprawne zakładanie, że tak będzie w przypadku innych kompilatorów. Możliwe jest również, że Twój kompilator zmieni się w przyszłej wersji.
2 powody, dla których warto używać std :: string:
std :: string może być używany zarówno dla tekstu, jak i dowolnych danych binarnych.
Powinieneś użyć metody .c_str (), gdy używasz swojego ciągu jako przykładu 1.
Powinieneś użyć metody .data (), gdy używasz swojego ciągu jako przykładu 2. Nie dlatego, że użycie .c_str () jest niebezpieczne w takich przypadkach, ale ponieważ jest bardziej wyraźne, że pracujesz z danymi binarnymi dla innych przeglądających Twój kod.
Możliwa pułapka z użyciem .data ()
Poniższy kod jest nieprawidłowy i może spowodować awarię w programie:
Dlaczego często implementujące programy powodują, że .data () i .c_str () robią to samo?
Ponieważ jest to bardziej wydajne. Jedynym sposobem, aby .data () zwróciło coś, co nie jest zakończone wartością zerową, byłoby skopiowanie ich wewnętrznego bufora .c_str () lub .data () lub po prostu użycie 2 buforów. Posiadanie pojedynczego bufora zakończonego wartością null zawsze oznacza, że podczas implementacji std :: string można zawsze użyć tylko jednego buforu wewnętrznego.
źródło
Odpowiedź została już udzielona, kilka uwag dotyczących celu: Swoboda wdrażania.
std::string
operacje - np. iteracja, konkatenacja i mutacja elementów - nie potrzebują terminatora zerowego. O ile nie przekażeszstring
funkcji, która oczekuje łańcucha zakończonego zerem, można ją pominąć.Pozwoliłoby to implementacji na współdzielenie przez podciągi rzeczywistych danych ciągu:
string::substr
mogłoby wewnętrznie przechowywać odniesienie do współdzielonych danych ciągu oraz zakresu początkowego / końcowego, unikając kopiowania (i dodatkowej alokacji) rzeczywistych danych ciągu. Implementacja odroczyłaby kopiowanie do momentu wywołania c_str lub zmodyfikowania któregokolwiek z ciągów. Żadna kopia nie powstałaby, gdyby po prostu przeczytano odpowiednie znaki.(implementacja kopiowania przy zapisie nie jest zbyt zabawna w środowiskach wielowątkowych, a typowe oszczędności pamięci / alokacji nie są dziś warte bardziej złożonego kodu, więc rzadko się to robi).
Podobnie
string::data
pozwala na inną reprezentację wewnętrzną, np. Lina (połączona lista segmentów struny). Może to znacznie usprawnić operacje wstawiania / wymiany. ponownie, lista segmentów musiałaby zostać zwinięta do jednego segmentu, gdy wywołujeszc_str
lubdata
.źródło
Cytat z
ANSI ISO IEC 14882 2003
(C ++ 03 Standard):źródło
Wszystkie poprzednie komendy są spójne, ale chciałbym również dodać, że zaczynając od c ++ 17, str.data () zwraca char * zamiast const char *
źródło
const
inon-const
przeciążenia są dostępne od C ++ 17.