W jednym z moich programów muszę połączyć się z jakimś starszym kodem, który działa z const char*
.
Powiedzmy, że mam strukturę, która wygląda następująco:
struct Foo
{
const char* server;
const char* name;
};
Moja aplikacja wyższego poziomu zajmuje się tylko tym std::string
, więc pomyślałem o użyciu, std::string::c_str()
aby odzyskać const char*
wskaźniki.
Ale co to jest życie c_str()
?
Czy mogę zrobić coś takiego, nie napotykając niezdefiniowanego zachowania?
{
std::string server = "my_server";
std::string name = "my_name";
Foo foo;
foo.server = server.c_str();
foo.name = name.c_str();
// We use foo
use_foo(foo);
// Foo is about to be destroyed, before name and server
}
A może mam od razu skopiować wynik w c_str()
inne miejsce?
Dziękuję Ci.
.c_str()
. Nie rozumiałem, dlaczego czasami dostaję tylko części struny, dopóki nie zrozumiałem, żeconst char*
nie żyje wiecznie, ale dopóki struna nie zostanie zniszczonaOdpowiedzi:
c_str()
Wynik staje się nieważna, jeślistd::string
jest zniszczona lub jeśli funkcja członek non-const napisu jest tzw. Dlatego zazwyczaj będziesz chciał zrobić jego kopię, jeśli chcesz go zachować.W przypadku naszego przykładu wygląda na to, że wyniki
c_str()
są używane bezpiecznie, ponieważ ciągi znaków nie są modyfikowane w tym zakresie. (Jednak nie wiemy, couse_foo()
lub~Foo()
może robić z tymi wartościami; jeśli skopiują ciągi w innym miejscu, powinni wykonać prawdziwą kopię , a nie tylko skopiowaćchar
wskaźniki).źródło
non-const member function of the string is called.
?const
słowem kluczowym. Taka funkcja może zmodyfikować zawartość ciągu, w którym to przypadku ciąg może wymagać ponownego przydzielenia pamięci dla zakończonej znakiem null wersji ciągu zwróconego przezc_str()
. Na przykładsize()
ilength()
sąconst
, więc możesz do nich dzwonić bez martwienia się o zmianę ciągu, aleclear()
tak nie jestconst
.Technicznie rzecz biorąc, twój kod jest w porządku.
ALE napisałeś w taki sposób, że łatwo złamać komuś, kto nie zna kodu. Jedynym bezpiecznym użyciem c_str () jest przekazanie jej jako parametru do funkcji. W przeciwnym razie narażasz się na problemy z konserwacją.
Przykład 1:
Więc jeśli chodzi o konserwację, to oczywiste:
Lepsze rozwiązanie:
Ale jeśli masz ciągi const, tak naprawdę ich nie potrzebujesz:
DOBRZE. Z jakiegoś powodu chcesz, aby były one ciągami:
Dlaczego nie używać ich tylko w wywołaniu:
źródło
Jest ważny, dopóki jeden z poniższych warunków nie wystąpi z odpowiednim
string
obiektem:Kod jest w porządku, chyba że zmodyfikujesz te
string
obiekty poc_str()
skopiowaniu s,foo
ale przeduse_foo()
wywołaniem.źródło
Wartość zwracana c_str () jest ważna tylko do następnego wywołania niestałej funkcji składowej dla tego samego ciągu
źródło
Wartość
const char*
zwracana zc_str()
jest ważna tylko do następnego wywołaniastd::string
obiektu niebędącego wartością stałą . W tym przypadku nic ci nie jest, ponieważstd::string
nadal znajdujesz się w zasięgu przez cały okres istnieniaFoo
i nie wykonujesz żadnych innych operacji, które zmieniłyby łańcuch podczas używania foo.źródło
Dopóki łańcuch nie zostanie zniszczony ani zmodyfikowany, użycie c_str () jest OK. Jeśli ciąg zostanie zmodyfikowany przy użyciu zwróconej wcześniej c_str (), to jest zdefiniowana implementacja.
źródło
Aby uzyskać kompletność, oto odniesienie i cytat z cppreference.com :
źródło