Das scheint weder möglich noch wünschenswert. 'staticDie Lebensdauer würde bedeuten, dass die Zeichenfolge niemals freigegeben wird, dh ein Speicherverlust. Warum brauchst du &'static strstatt &'a strfür ein passendes 'a?
3
Wie würde es aussehen, es &'a str dann umzuwandeln ?
Christoph
Via as_slice. Es wäre einfacher zu helfen, wenn Sie beschreiben würden, welches konkrete Problem Sie lösen möchten und auf welche Probleme Sie dabei stoßen.
Beachten Sie SendStrauch einen Typ, der entweder eine eigene Zeichenfolge oder eine statische Zeichenfolge ist.
Chris Morgan
Antworten:
132
Aktualisiert für Rust 1.0
Sie können nicht &'static strvon a erhalten, Stringweil Strings möglicherweise nicht für das gesamte Leben Ihres Programms lebt, und das ist, was &'staticLeben bedeutet. Sie können nur ein Slice erhalten, das nach seiner Stringeigenen Lebensdauer parametrisiert ist.
Um von einem Stringzu einem Slice zu wechseln &'a str, können Sie die Slicing-Syntax verwenden:
let s:String="abcdefg".to_owned();let s_slice:&str=&s[..];// take a full slice of the string
Alternativ können Sie die Tatsache verwenden, dass eine explizite Neuausleihe Stringimplementiert Deref<Target=str>und durchgeführt wird:
let s_slice:&str=&*s;// s : String // *s : str (via Deref<Target=str>)// &*s: &str
Es gibt noch einen anderen Weg, der eine noch präzisere Syntax ermöglicht, der jedoch nur verwendet werden kann, wenn der Compiler den gewünschten Zieltyp bestimmen kann (z. B. in Funktionsargumenten oder explizit typisierten Variablenbindungen). Es wird als Deref-Zwang bezeichnet und ermöglicht die Verwendung eines einfachen &Operators. Der Compiler fügt automatisch eine geeignete Menge von *s ein, basierend auf dem Kontext:
let s_slice:&str=&s;// okayfn take_name(name:&str){...}
take_name(&s);// okay as welllet not_correct =&s;// this will give &String, not &str,// because the compiler does not know// that you want a &str
Beachten Sie, dass dieses Muster nicht eindeutig für String/ ist. &strSie können es für jedes Typenpaar verwenden, das Derefbeispielsweise mit CString/ CStrund OsString/ OsStrvom std::ffiModul oder PathBuf/ Pathvom std::pathModul verbunden ist.
In Rust 1.10 können Sie stattdessen let s_slice: &str = &s[..];einfach let s_slice: &str = s.as_str();
Folgendes
3
Manchmal lebt die ursprüngliche Zeichenfolge nicht genug, wie in einem Match-Block. Das wird zu einem führen 's' does not live long enough error.
Dereckson
37
Sie können es tun, aber es geht darum , die Erinnerung an die zu verlierenString . Dies sollten Sie nicht leichtfertig tun. Durch das Lecken des Speichers von Stringgarantieren wir, dass der Speicher niemals freigegeben wird (also das Leck). Daher können alle Verweise auf das innere Objekt so interpretiert werden, dass sie die 'staticLebensdauer haben.
fn string_to_static_str(s:String)->&'staticstr{Box::leak(s.into_boxed_str())}fn main(){letmut s =String::new();
std::io::stdin().read_line(&mut s).unwrap();let s:&'staticstr= string_to_static_str(s);}
Stringgarantiert, dass der Speicher am Leben bleibt, solange das Objekt nicht gelöscht wurde. Da mem::forgetgarantiert wird, dass das Objekt niemals gelöscht wird, ist garantiert, dass der Verweis auf das Enthaltene strniemals ungültig wird. Somit können wir behaupten, dass es sich um eine 'staticReferenz handelt
oli_obk
1
Dies war unglaublich hilfreich für meine Rust-Anwendung, die eine Stringin eine zwingen musste, &'static strdamit aus dem Original erstellte Token für Stringalle Threads verfügbar waren. Ohne dies würde sich der Rust-Compiler beschweren, dass mein StringLeben am Ende der Hauptfunktion endete, was nicht gut genug war, weil es keine 'staticGarantie gab.
mmstick
1
@mmstick: Die bessere Lösung in diesem Fall wäre die Verwendung crossbeamvon Threads mit
Gültigkeitsbereich
3
@mmstick: Wenn Sie Ihre gesamte Anwendung in einen Crossbeam-Bereich einfügen und die Zeichenfolge außerhalb des Bereichs erstellen, erhalten Sie genau das.
oli_obk
1
Diese Antwort ist großartig! Beide sagten mir, wie man ein statisches String-Slice erstellt, und überzeugten mich, es nicht zu tun! Ich habe mich entschieden, meine App so umzugestalten, dass an so vielen Stellen keine statischen String-Slices verwendet werden.
Paul Chernoch
21
Ab Rust Version 1.26 ist es möglich , eine konvertieren Stringzu , &'static strohne den unsafeCode ein :
Dies konvertiert die StringInstanz in eine Box strund leckt sie sofort. Dadurch wird die gesamte überschüssige Kapazität freigegeben, die der String derzeit möglicherweise belegt.
Beachten Sie, dass es fast immer Lösungen gibt, die gegenüber undichten Objekten vorzuziehen sind, z. B. die Verwendung der crossbeamKiste, wenn Sie den Status zwischen Threads teilen möchten.
TL; DR: Sie können eine &'static strvon einer bekommen, Stringdie selbst ein 'staticLeben lang hat.
Obwohl die anderen Antworten korrekt und am nützlichsten sind, gibt es einen (nicht so nützlichen) Randfall, in dem Sie tatsächlich a Stringin a konvertieren können &'static str:
Die Lebensdauer einer Referenz muss immer kürzer oder gleich der Lebensdauer des referenzierten Objekts sein. Das heißt, das referenzierte Objekt muss länger (oder gleich lange) leben als die Referenz. Da 'staticdies die gesamte Lebensdauer eines Programms bedeutet, gibt es keine längere Lebensdauer. Eine gleiche Lebensdauer wird jedoch ausreichen. Wenn a Stringalso eine Lebensdauer von hat 'static, können Sie eine &'static strReferenz daraus erhalten.
Das Erstellen eines staticTyps Stringist mit Rust 1.31 theoretisch möglich geworden, als die const fnFunktion veröffentlicht wurde. Leider ist die einzige konstante Funktion einer Rückkehr Stringist String::new()zur Zeit, und es ist immer noch hinter einem Feature - Gate (so Rust allabendlich für jetzt ist erforderlich).
Der folgende Code führt also die gewünschte Konvertierung durch (unter Verwendung von nächtlichen) ... und hat tatsächlich keine praktische Verwendung, außer der Vollständigkeit des Nachweises, dass dies in diesem Randfall möglich ist.
'static
Die Lebensdauer würde bedeuten, dass die Zeichenfolge niemals freigegeben wird, dh ein Speicherverlust. Warum brauchst du&'static str
statt&'a str
für ein passendes'a
?&'a str
dann umzuwandeln ?as_slice
. Es wäre einfacher zu helfen, wenn Sie beschreiben würden, welches konkrete Problem Sie lösen möchten und auf welche Probleme Sie dabei stoßen.SendStr
auch einen Typ, der entweder eine eigene Zeichenfolge oder eine statische Zeichenfolge ist.Antworten:
Aktualisiert für Rust 1.0
Sie können nicht
&'static str
von a erhalten,String
weilString
s möglicherweise nicht für das gesamte Leben Ihres Programms lebt, und das ist, was&'static
Leben bedeutet. Sie können nur ein Slice erhalten, das nach seinerString
eigenen Lebensdauer parametrisiert ist.Um von einem
String
zu einem Slice zu wechseln&'a str
, können Sie die Slicing-Syntax verwenden:Alternativ können Sie die Tatsache verwenden, dass eine explizite Neuausleihe
String
implementiertDeref<Target=str>
und durchgeführt wird:Es gibt noch einen anderen Weg, der eine noch präzisere Syntax ermöglicht, der jedoch nur verwendet werden kann, wenn der Compiler den gewünschten Zieltyp bestimmen kann (z. B. in Funktionsargumenten oder explizit typisierten Variablenbindungen). Es wird als Deref-Zwang bezeichnet und ermöglicht die Verwendung eines einfachen
&
Operators. Der Compiler fügt automatisch eine geeignete Menge von*
s ein, basierend auf dem Kontext:Beachten Sie, dass dieses Muster nicht eindeutig für
String
/ ist.&str
Sie können es für jedes Typenpaar verwenden, dasDeref
beispielsweise mitCString
/CStr
undOsString
/OsStr
vomstd::ffi
Modul oderPathBuf
/Path
vomstd::path
Modul verbunden ist.quelle
let s_slice: &str = &s[..];
einfachlet s_slice: &str = s.as_str();
's' does not live long enough error
.Sie können es tun, aber es geht darum , die Erinnerung an die zu verlieren
String
. Dies sollten Sie nicht leichtfertig tun. Durch das Lecken des Speichers vonString
garantieren wir, dass der Speicher niemals freigegeben wird (also das Leck). Daher können alle Verweise auf das innere Objekt so interpretiert werden, dass sie die'static
Lebensdauer haben.quelle
String
garantiert, dass der Speicher am Leben bleibt, solange das Objekt nicht gelöscht wurde. Damem::forget
garantiert wird, dass das Objekt niemals gelöscht wird, ist garantiert, dass der Verweis auf das Enthaltenestr
niemals ungültig wird. Somit können wir behaupten, dass es sich um eine'static
Referenz handeltString
in eine zwingen musste,&'static str
damit aus dem Original erstellte Token fürString
alle Threads verfügbar waren. Ohne dies würde sich der Rust-Compiler beschweren, dass meinString
Leben am Ende der Hauptfunktion endete, was nicht gut genug war, weil es keine'static
Garantie gab.crossbeam
von Threads mitAb Rust Version 1.26 ist es möglich , eine konvertieren
String
zu ,&'static str
ohne denunsafe
Code ein :Dies konvertiert die
String
Instanz in eine Boxstr
und leckt sie sofort. Dadurch wird die gesamte überschüssige Kapazität freigegeben, die der String derzeit möglicherweise belegt.Beachten Sie, dass es fast immer Lösungen gibt, die gegenüber undichten Objekten vorzuziehen sind, z. B. die Verwendung der
crossbeam
Kiste, wenn Sie den Status zwischen Threads teilen möchten.quelle
TL; DR: Sie können eine
&'static str
von einer bekommen,String
die selbst ein'static
Leben lang hat.Obwohl die anderen Antworten korrekt und am nützlichsten sind, gibt es einen (nicht so nützlichen) Randfall, in dem Sie tatsächlich a
String
in a konvertieren können&'static str
:Die Lebensdauer einer Referenz muss immer kürzer oder gleich der Lebensdauer des referenzierten Objekts sein. Das heißt, das referenzierte Objekt muss länger (oder gleich lange) leben als die Referenz. Da
'static
dies die gesamte Lebensdauer eines Programms bedeutet, gibt es keine längere Lebensdauer. Eine gleiche Lebensdauer wird jedoch ausreichen. Wenn aString
also eine Lebensdauer von hat'static
, können Sie eine&'static str
Referenz daraus erhalten.Das Erstellen eines
static
TypsString
ist mit Rust 1.31 theoretisch möglich geworden, als dieconst fn
Funktion veröffentlicht wurde. Leider ist die einzige konstante Funktion einer RückkehrString
istString::new()
zur Zeit, und es ist immer noch hinter einem Feature - Gate (so Rust allabendlich für jetzt ist erforderlich).Der folgende Code führt also die gewünschte Konvertierung durch (unter Verwendung von nächtlichen) ... und hat tatsächlich keine praktische Verwendung, außer der Vollständigkeit des Nachweises, dass dies in diesem Randfall möglich ist.
quelle