स्ट्रिंग को एक & 'स्टैटिक स्ट्रैस' में कैसे बदलें


91

मैं a Stringको a में कैसे परिवर्तित करूं &str? विशेष रूप से, मैं इसे जीवन भर ( ) के strसाथ परिवर्तित करना चाहूंगा ।static&'static str


यह न तो संभव प्रतीत होता है और न ही वांछनीय। 'staticजीवनकाल का अर्थ यह होगा कि स्ट्रिंग को कभी नहीं हटाया जाएगा, अर्थात मेमोरी रिसाव। आपको कुछ उपयुक्त के &'static strबदले की आवश्यकता क्यों है ? &'a str'a

3
इसे &'a str तब रूपांतरित करना कैसा लगेगा ?
क्रिस्टोफ़

वाया as_slice। ऐसा करने में मदद करना आसान होगा यदि आपने बताया कि ऐसा करने में आप किस ठोस समस्या को हल करने की कोशिश कर रहे हैं और आपको किन समस्याओं का सामना करना पड़ रहा है।

यह भी ध्यान दें SendStr, एक प्रकार जो या तो एक स्वामित्व स्ट्रिंग या स्थिर स्ट्रिंग है।
क्रिस मॉर्गन

जवाबों:


134

रस्ट 1.0 के लिए अपडेट किया गया

आप अपने कार्यक्रम के पूरे जीवन के लिए नहीं रह सकते हैं, और यह जीवन भर का मतलब है क्योंकि आप &'static strसे प्राप्त नहीं कर सकते हैं । आप केवल एक स्लाइस मानदंड प्राप्त कर सकते हैं जो स्वयं का जीवनकाल है।StringString&'staticString

ए से जाना है Stringएक स्लाइस लिए &'a strआप स्लाइसिंग सिंटैक्स का उपयोग कर सकते हैं:

let s: String = "abcdefg".to_owned();
let s_slice: &str = &s[..];  // take a full slice of the string

वैकल्पिक रूप से, आप इस तथ्य का उपयोग कर सकते हैं कि Stringलागू होता है Deref<Target=str>और एक स्पष्ट रीबोरिंग करता है:

let s_slice: &str = &*s;  // s  : String 
                          // *s : str (via Deref<Target=str>)
                          // &*s: &str

एक और तरीका है जो और भी अधिक संक्षिप्त वाक्य रचना के लिए अनुमति देता है लेकिन इसका उपयोग केवल तभी किया जा सकता है जब कंपाइलर वांछित लक्ष्य प्रकार (जैसे फ़ंक्शन तर्क या स्पष्ट रूप से टाइप किए गए चर बाइंडिंग) निर्धारित करने में सक्षम हो। यह कहा जाता है deref coercion और यह बस &ऑपरेटर का उपयोग करने की अनुमति देता है , और संकलक स्वचालित रूप *से संदर्भ के आधार पर उपयुक्त मात्रा में सम्मिलित करेगा :

let s_slice: &str = &s;  // okay

fn take_name(name: &str) { ... }
take_name(&s);           // okay as well

let not_correct = &s;    // this will give &String, not &str,
                         // because the compiler does not know
                         // that you want a &str

ध्यान दें कि यह पैटर्न के लिए अद्वितीय नहीं है String/ &str- आप जिसके माध्यम से जुड़े हुए हैं प्रकार की प्रत्येक जोड़ी के साथ उपयोग कर सकते हैं Deref, उदाहरण के लिए, के साथ CString/ CStrऔर OsString/ OsStrसे std::ffiमॉड्यूल या PathBuf/ Pathसे std::pathमॉड्यूल।


29
जंग में let s_slice: &str = &s[..];आप के बजाय 1.10 बस यह कर सकते हैं:let s_slice: &str = s.as_str();
Shnatsel

3
शायद ही कभी, मूल स्ट्रिंग पर्याप्त नहीं रहती है, जैसे कि एक मैच {...} ब्लॉक। वह नेतृत्व करेगा 's' does not live long enough error
डेरेकसन

41

आप इसे कर सकते हैं, लेकिन इसमें मेमोरी को लीकString करना शामिल है । यह कुछ ऐसा नहीं है जिसे आपको हल्के ढंग से करना चाहिए। की मेमोरी को लीक करके String, हम गारंटी देते हैं कि मेमोरी को कभी भी मुक्त नहीं किया जाएगा (इस प्रकार रिसाव)। इसलिए, आंतरिक वस्तु के किसी भी संदर्भ को 'staticजीवनकाल होने के रूप में व्याख्या किया जा सकता है ।

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let s: &'static str = string_to_static_str(s);
}

8
Stringएक गारंटी देता है, कि जब तक वस्तु को गिराया नहीं गया है, स्मृति जीवित रहती है। चूंकि mem::forgetगारंटी देता है कि ऑब्जेक्ट कभी भी गिराया नहीं जाएगा, इसलिए हम गारंटी देते हैं कि निहित का संदर्भ strकभी भी अमान्य नहीं होगा। इस प्रकार हम दावा कर सकते हैं कि यह एक 'staticसंदर्भ है
oli_obk

1
यह मेरे रस्ट एप्लिकेशन के लिए अविश्वसनीय रूप से मददगार था, जिसे एक Stringमें समेटने की आवश्यकता थी &'static strताकि मूल से निर्मित टोकन Stringसभी थ्रेड्स में उपलब्ध हों। इसके बिना, रस्ट कंपाइलर शिकायत करेगा कि मेरा Stringजीवनकाल मुख्य समारोह के अंत में समाप्त हो गया था, जो पर्याप्त नहीं था क्योंकि इसकी 'staticगारंटी नहीं थी ।
mmstick

1
@mmstick: उस मामले में बेहतर समाधान crossbeamथ्रेड्स का उपयोग और स्कोप करना होगा
oli_obk

3
@mmstick: यदि आप अपने पूरे एप्लिकेशन को एक क्रॉसबीम दायरे में रखते हैं और स्ट्रिंग को दायरे से बाहर बनाते हैं, तो आप ठीक वैसा ही प्राप्त करते हैं।
oli_obk

1
यह जवाब बहुत अच्छा है! यह दोनों ने मुझे बताया कि कैसे एक स्थिर स्ट्रिंग स्लाइस बनाने के लिए और मुझे यह नहीं करने के लिए आश्वस्त किया! मैंने अपने ऐप को इतने सारे स्थानों पर स्थिर स्ट्रिंग स्लाइस का उपयोग न करने के लिए चुना।
पॉल चेरोच

22

जंग संस्करण 1.26 के रूप में, कोड का उपयोग किए बिना ए Stringको परिवर्तित करना संभव है :&'static strunsafe

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

यह Stringउदाहरण को एक बॉक्सिंग में परिवर्तित करता है strऔर तुरंत लीक कर देता है। यह सभी अतिरिक्त क्षमता को मुक्त करता है जो वर्तमान में स्ट्रिंग पर कब्जा कर सकते हैं।

ध्यान दें कि लगभग हमेशा समाधान होते हैं जो वस्तुओं को लीक करने के लिए बेहतर होते हैं, उदाहरण के लिए crossbeamटोकरे का उपयोग करते हुए यदि आप थ्रेड्स के बीच स्थिति साझा करना चाहते हैं।


2

TL; DR: आप एक &'static strसे प्राप्त कर सकते हैं Stringजो अपने आप में एक 'staticजीवनकाल है।

हालांकि अन्य उत्तर सही और सबसे उपयोगी हैं, वहाँ एक (इतना उपयोगी नहीं) बढ़त मामला है, जहां आप वास्तव में एक Stringको एक में बदल सकते हैं &'static str:

एक संदर्भ का जीवनकाल हमेशा संदर्भित वस्तु के जीवनकाल के बराबर या उससे कम होना चाहिए। यानी संदर्भित वस्तु को संदर्भ की तुलना में अधिक समय तक (या बराबर लंबा) रहना पड़ता है। चूंकि 'staticएक कार्यक्रम के पूरे जीवनकाल का मतलब है, एक लंबा जीवनकाल मौजूद नहीं है। लेकिन एक समान जीवनकाल पर्याप्त होगा। इसलिए यदि किसी Stringका जीवनकाल है 'static, तो आप उससे एक &'static strसंदर्भ प्राप्त कर सकते हैं ।

एक staticप्रकार Stringका निर्माण सैद्धांतिक रूप से Rust 1.31 के साथ संभव हो गया है जब const fnसुविधा जारी की गई थी। दुर्भाग्य से, एकमात्र कॉन्स्टेंट फंक्शन लौट रहा है, Stringजो String::new()वर्तमान में है, और यह अभी भी एक फीचर गेट के पीछे है (इसलिए अब रात को जंग जरूरी है)।

तो निम्नलिखित कोड वांछित रूपांतरण (रात का उपयोग करके) करता है ... और वास्तव में यह दिखाने की पूर्णता को छोड़कर कोई व्यावहारिक उपयोग नहीं है कि यह इस किनारे के मामले में संभव है।

#![feature(const_string_new)]

static MY_STRING: String = String::new();

fn do_something(_: &'static str) {
    // ...
}

fn main() {
    do_something(&MY_STRING);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.