Kiedy potrzebny jest łańcuch zakończony zerem w scenariuszu tylko do odczytu?

10

Bawiłem się std::string_viewbiblioteką i zastanawiałem się nad zmianą bazy kodu, nad którą pracowałem std::string_viewtak często, jak to możliwe. Jednak w wielu wątkach, które przeczytałem na temat tego, kiedy i gdzie użyć std::string_viewzamiast const std::string &. Widziałem wiele odpowiedzi mówiących: „Kiedy nie potrzebujesz łańcucha zakończonego znakiem zerowym”. Kiedy zacząłem szukać w Internecie, „kiedy potrzebujesz łańcucha zakończonego znakiem zerowym?” Tak naprawdę nie spotkałem żadnych pomocnych odpowiedzi na ten temat.

Mogę wymyślić przykład zewnętrznej biblioteki, do której link będzie się wymagał std::string. W takim przypadku potrzebujesz łańcucha zakończonego znakiem zerowym, ponieważ biblioteka tego wymaga. Wydaje mi się, że innym przykładem byłaby potrzeba modyfikacji samego łańcucha, ale nie przepuszczalibyśmy go const &, gdybyśmy musieli go zmodyfikować.

Kiedy więc miałbyś użyć łańcucha zakończonego zerą?

Linki, na które spojrzałem:

  1. Jak dokładnie std :: string_view jest szybszy niż const std :: string &?
  2. Kiedy mam przekazać const & std :: string zamiast std :: string_view?
  3. Dlaczego tylko widok ciągów?
  4. Czy ma sens używanie const std :: string & arguments w C ++ 17?
Sailanarmo
źródło
5
Głównie do interfejsu API C.
orzech
@uneven_mark czy możesz podać przykład takiego?
Sailanarmo
Akceptowana odpowiedź na czwarte pytanie, które łączysz, wydaje się odpowiadać na to pytanie.
François Andrieux
1
@Sailanarmo Większość funkcji z np. POSIX lub innej biblioteki C biorącej const char*argument. Odpowiedź eeroriki ma przykład.
orzech
1
@ FrançoisAndrieux, więc tak naprawdę odpowiedź brzmi: „Tak długo, jak interfejs API nie wymaga łańcucha zakończonego znakiem NUL?”
Sailanarmo

Odpowiedzi:

10

Kiedy potrzebujesz łańcucha zakończonego znakiem NULL?

Potrzebujesz łańcucha zakończonego znakiem NULL, ilekroć używany interfejs API mówi, że jest potrzebny. To wymaganie jest wszechobecne w interfejsach C i nie jest wyraźnie określone w niektórych dokumentach. Jeśli argumentem funkcji jest char*(być może const) i nie ma argumentu długości, należy przyjąć wymaganie, chyba że dokumentacja mówi inaczej.

Weźmy na przykład funkcję execve(ze standardu POSIX):

int execve(const char *pathname, char *const argv[], char *const envp[]);

Jeśli przekażesz argument zakończony wartością inną niż null jako pathname, zachowanie twojego programu będzie niezdefiniowane.

eerorika
źródło
Więc w tym przypadku nazwa ścieżki, jeśli std::stringmiałaby to być , byłaby wykonywana jak execve(pathname.c_str(),...,...)?
Sailanarmo
6

Jest to dość łatwe do poznania. Jeśli wywołujesz funkcję, która po prostu pobiera łańcuch c ( char*/ const char*), potrzebujesz łańcucha zakończonego znakiem null, ponieważ jest to jedyny sposób, aby dowiedzieć się, gdzie jest koniec łańcucha.

Jeśli zamiast tego masz funkcję, która przyjmuje rozmiar plus char*/ const char*lub tylko dwa wskaźniki oznaczające początek i koniec danych, nie potrzebujesz łańcucha zakończonego znakiem null, ponieważ masz / możesz uzyskać rozmiar łańcucha bez iteracji do terminator zerowy.

NathanOliver
źródło