जवाबों:
String
डायनामिक हीप स्ट्रिंग प्रकार है, जैसे Vec
: इसका उपयोग तब करें जब आपको अपने स्ट्रिंग डेटा को स्वयं या संशोधित करने की आवश्यकता हो।
str
स्मृति में कहीं कहीं गतिशील लंबाई के UTF-8 बाइट्स का एक अपरिवर्तनीय 1 अनुक्रम है। चूंकि आकार अज्ञात है, कोई केवल एक पॉइंटर के पीछे इसे संभाल सकता है। इसका मतलब यह है कि str
आमतौर पर 2 के रूप में प्रकट होता है &str
: कुछ यूटीएफ -8 डेटा का संदर्भ, जिसे आमतौर पर "स्ट्रिंग स्लाइस" या सिर्फ एक "स्लाइस" कहा जाता है। एक टुकड़ा केवल कुछ डेटा पर एक दृश्य है, और वह डेटा कहीं भी हो सकता है, जैसे
"foo"
एक है &'static str
। जब प्रोग्राम चलता है तो डेटा को निष्पादन योग्य में हार्डकोड किया जाता है और मेमोरी में लोड किया जाता है।String
: डेटा के String
एक &str
दृश्य के लिए dereferencesString
।स्टैक पर : उदाहरण के लिए, एक स्टैक-आबंटित बाइट सरणी बनाता है, और फिर उस के रूप में उस डेटा का&str
एक दृश्य प्राप्त करता है :
use std::str;
let x: &[u8] = &[b'a', b'b', b'c'];
let stack_str: &str = str::from_utf8(x).unwrap();
सारांश में, String
यदि आपको स्वामित्व वाले स्ट्रिंग डेटा की आवश्यकता है (जैसे कि अन्य थ्रेड्स के लिए तार पास करना, या रनटाइम पर उनका निर्माण करना), और उपयोग करें &str
यदि आपको केवल स्ट्रिंग के दृश्य की आवश्यकता है।
यह एक वेक्टर Vec<T>
और एक स्लाइस &[T]
के बीच संबंध के समान है, और सामान्य प्रकारों के लिए उप-मूल्य T
और उप-संदर्भ &T
के बीच संबंध के समान है ।
1 ए str
तय-लंबाई है; आप अंत से परे बाइट्स नहीं लिख सकते हैं, या अमान्य बाइट्स को पीछे छोड़ सकते हैं। चूंकि UTF-8 एक चर-चौड़ाई एन्कोडिंग है, यह प्रभावी रूप से सभी str
को कई मामलों में अपरिवर्तनीय होने के लिए मजबूर करता है। सामान्य तौर पर, म्यूटेशन के लिए पहले की तुलना में अधिक या कम बाइट्स लिखने की आवश्यकता होती है (उदाहरण के लिए a
(1 बाइट की जगह ) एक ä
(2+ बाइट्स) के साथ अधिक कमरे बनाने की आवश्यकता होती है str
। विशिष्ट तरीके हैं जो एक &str
जगह को संशोधित कर सकते हैं , ज्यादातर वे जो केवल ASCII वर्णों को संभालते हैं, जैसे make_ascii_uppercase
।
2 डायनामिक आकार के प्रकारोंRc<str>
को संदर्भ के एक क्रम के लिए अनुमति देते हैं जैसे कि रूस्ट 1.2 से यूटीएफ -8 बाइट्स गिना जाता है। जंग 1.21 आसानी से इन प्रकारों को बनाने की अनुमति देता है।
[u8; N]
,।
Rc<str>
और Arc<str>
अब मानक पुस्तकालय के माध्यम से उपयोग करने योग्य हैं।
मैं एक सी ++ पृष्ठभूमि है और मैं इसे बहुत के बारे में सोचना उपयोगी पाया String
और &str
सी ++ संदर्भ में:
String
की तरह है std::string
; यह स्मृति का मालिक है और स्मृति के प्रबंधन का गंदा काम करता है।&str
की तरह है char*
(लेकिन थोड़ा और अधिक परिष्कृत); यह हमें उसी तरह से एक चंक की शुरुआत की ओर इशारा करता है जिस तरह से आप सामग्री की ओर संकेत कर सकते हैं std::string
।क्या दोनों में से कोई गायब होने वाला है? मुझे ऐसा नहीं लगता है। वे दो उद्देश्यों की सेवा करते हैं:
String
बफर रखता है और उपयोग करने के लिए बहुत व्यावहारिक है। &str
हल्का है और इसे स्ट्रिंग्स में "देखने" के लिए उपयोग किया जाना चाहिए। आप नई मेमोरी को आवंटित करने की आवश्यकता के बिना खोज, विभाजन, पार्स और यहां तक कि विखंडू को बदल सकते हैं।
&str
अंदर देखने के String
रूप में यह कुछ स्ट्रिंग शाब्दिक को इंगित कर सकता है। निम्नलिखित कोड को String
प्रबंधित मेमोरी में शाब्दिक स्ट्रिंग को कॉपी करने की आवश्यकता है :
let a: String = "hello rust".into();
निम्नलिखित कोड आपको कॉपी के बिना ही शाब्दिक का उपयोग करने देता है (केवल हालांकि पढ़ें)
let a: &str = "hello rust";
str
, केवल के रूप में इस्तेमाल किया &str
, एक स्ट्रिंग टुकड़ा, एक UTF-8 बाइट सरणी के लिए एक संदर्भ है।
String
~str
यूटीएफ -8 बाइट सरणी के रूप में , एक बढ़ने योग्य, स्वामित्व वाला है।
~str
अब हुआ करता थाBox<str>
~str
बढ़ने योग्य था जबकि बढ़ने Box<str>
योग्य नहीं है। (यह ~str
और ~[T]
जादुई उगने वाली दाढ़ी थे किसी अन्य के विपरीत ~
-object, वास्तव में था क्यों String
और Vec<T>
शुरू किए गए थे, ताकि नियम सभी सीधा और निरंतर चल रहे थे।)
वे वास्तव में पूरी तरह से अलग हैं। सबसे पहले, str
यह एक प्रकार की चीज़ के अलावा कुछ नहीं है; यह केवल प्रकार के स्तर के बारे में तर्क दिया जा सकता है क्योंकि यह एक तथाकथित गतिशील रूप से आकार प्रकार (DST) है। आकार str
लेता है संकलन समय पर नहीं जाना जा सकता है और रनटाइम जानकारी पर निर्भर करता है - इसे एक चर में संग्रहीत नहीं किया जा सकता है क्योंकि संकलक को संकलन समय पर यह जानना होगा कि प्रत्येक चर का आकार क्या है। A str
वैचारिक रूप u8
से गारंटी के साथ बाइट्स की एक पंक्ति है जो वैध UTF-8 बनाता है। पंक्ति कितनी बड़ी है? कोई भी रनटाइम तक नहीं जानता है इसलिए इसे एक चर में संग्रहीत नहीं किया जा सकता है।
दिलचस्प बात यह है कि एक है &str
एक करने के लिए या किसी अन्य सूचक str
की तरह Box<str>
करता है क्रम पर मौजूद हैं। यह एक तथाकथित "वसा सूचक" है; यह अतिरिक्त जानकारी के साथ एक संकेतक है (इस मामले में उस चीज़ का आकार जो इसे इंगित कर रहा है) इसलिए यह दोगुना बड़ा है। वास्तव में, यह &str
एक String
(लेकिन नहीं &String
) के काफी करीब है । ए &str
दो शब्द है; पहले बाइट की एक पॉइंटर str
और दूसरी संख्या जो बताती है कि यह कितने बाइट्स str
है।
जो कहा गया है, उसके विपरीत, str
अपरिवर्तनीय होने की आवश्यकता नहीं है। यदि आप के लिए एक &mut str
विशेष सूचक के रूप में प्राप्त कर सकते हैं str
, तो आप इसे और सभी सुरक्षित कार्यों को म्यूट कर सकते हैं जो गारंटी देते हैं कि UTF-8 बाधा को बरकरार रखा जाता है क्योंकि यदि इसका उल्लंघन किया जाता है तो हमारे पास अपरिभाषित व्यवहार होता है क्योंकि पुस्तकालय इस बाधा को मानता है। सच है और इसके लिए जाँच नहीं करता है।
तो एक क्या है String
? वह तीन शब्द हैं; दो इसके लिए समान हैं, &str
लेकिन यह एक तीसरा शब्द जोड़ता है जो str
कि ढेर पर बफर की क्षमता है , हमेशा ढेर पर ( str
यह जरूरी नहीं है कि यह ढेर पर हो) इससे पहले कि यह भर जाता है और इसे फिर से आवंटित करना पड़ता है। String
मूल रूप से मालिक एक str
के रूप में वे कहते हैं; यह इसे नियंत्रित करता है और इसे आकार बदल सकता है और इसे तब फिट कर सकता है जब यह फिट दिखता है। तो एक String
के रूप में कहा जाता है कि एक &str
से एक के करीब है str
।
एक और बात है Box<str>
; यह भी एक मालिक है str
और इसका रनटाइम प्रतिनिधित्व समान है, &str
लेकिन यह इसके str
विपरीत का भी मालिक है , &str
लेकिन यह इसे आकार नहीं दे सकता है क्योंकि यह इसकी क्षमता को नहीं जानता है इसलिए मूल Box<str>
रूप से एक निश्चित-लंबाई के रूप में देखा जा सकता है String
जिसे आकार नहीं दिया जा सकता है (आप कर सकते हैं String
यदि आप इसे आकार बदलना चाहते हैं तो हमेशा इसे रूपांतरित करें )।
एक समान समान संबंध मौजूद है [T]
और Vec<T>
इसके अलावा कोई UTF-8 बाधा नहीं है और यह किसी भी प्रकार को पकड़ सकता है जिसका आकार गतिशील नहीं है।
के उपयोग str
पर प्रकार के स्तर के साथ सामान्य कपोल-कल्पना बनाने के लिए ज्यादातर है &str
; यह आसानी से लक्षण लिखने में सक्षम होने के लिए प्रकार के स्तर पर मौजूद है। सिद्धांत str
रूप में एक प्रकार की चीज का अस्तित्व होना आवश्यक नहीं था और केवल &str
इसका मतलब है कि बहुत सारे अतिरिक्त कोड लिखने होंगे जो अब सामान्य हो सकते हैं।
&str
सुपर उपयोगी String
है कॉपी करने के लिए एक के बिना कई अलग अलग substrates है करने में सक्षम होने के लिए; के रूप में एक ने कहा कि String
मालिकstr
ढेर यह प्रबंधन करता है पर और यदि आप केवल एक की सबस्ट्रिंग बना सकते हैं String
एक नए के साथ String
कॉपी क्योंकि जंग में सब कुछ केवल स्मृति सुरक्षा से निपटने के लिए एक ही स्वामी हो सकता करने के लिए होगा। तो उदाहरण के लिए आप एक स्ट्रिंग टुकड़ा कर सकते हैं:
let string: String = "a string".to_string();
let substring1: &str = &string[1..3];
let substring2: &str = &string[2..4];
हमारे पास str
एक ही स्ट्रिंग के दो अलग-अलग विकल्प हैं । string
वह है जो str
हीप पर वास्तविक पूर्ण बफर का मालिक है और &str
सबस्ट्रिंग ढेर पर उस बफर के लिए केवल वसा संकेत हैं।
std::String
बस का एक वेक्टर है u8
। आप इसकी परिभाषा स्रोत कोड में पा सकते हैं । यह ढेर-आवंटित और बढ़ने योग्य है।
#[derive(PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
vec: Vec<u8>,
}
str
एक आदिम प्रकार है, जिसे स्ट्रिंग स्लाइस भी कहा जाता है । एक स्ट्रिंग टुकड़ा का निश्चित आकार है। एक शाब्दिक स्ट्रिंग की तरह let test = "hello world"
है &'static str
। test
इस सांख्यिकीय रूप से आवंटित स्ट्रिंग का एक संदर्भ है।
&str
उदाहरण के लिए, संशोधित नहीं किया जा सकता
let mut word = "hello world";
word[0] = 's';
word.push('\n');
str
&mut str
उदाहरण के लिए परस्पर स्लाइस है :
pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)
let mut s = "Per Martin-Löf".to_string();
{
let (first, last) = s.split_at_mut(3);
first.make_ascii_uppercase();
assert_eq!("PER", first);
assert_eq!(" Martin-Löf", last);
}
assert_eq!("PER Martin-Löf", s);
लेकिन UTF-8 में एक छोटा सा बदलाव इसकी बाइट की लंबाई को बदल सकता है, और एक स्लाइस इसके संदर्भ को पुनः प्राप्त नहीं कर सकता है।
आसान शब्दों में, String
डीटाइपाइप को ढेर (जैसे Vec
) पर संग्रहीत किया जाता है , और आपके पास उस स्थान तक पहुंच होती है।
&str
एक स्लाइस प्रकार है। इसका मतलब है कि यह सिर्फ एक पहले से ही String
कहीं मौजूद ढेर का संदर्भ है ।
&str
रनटाइम पर कोई आवंटन नहीं करता है। तो, स्मृति कारणों के लिए, आप &str
पर उपयोग कर सकते हैं String
। लेकिन, इस बात का ध्यान रखें कि उपयोग करते समय &str
आपको स्पष्ट जीवनकाल से निपटना पड़ सकता है।
str
वह view
पहले से ही String
ढेर में मौजूद है।
C # और Java लोगों के लिए:
String
===StringBuilder
&str
=== (अपरिवर्तनीय) तारमैं &str
एक स्ट्रिंग पर एक दृश्य के रूप में सोचना पसंद करता हूं , जैसे जावा / सी # में एक प्रशिक्षु स्ट्रिंग जहां आप इसे बदल नहीं सकते हैं, केवल एक नया बना सकते हैं।
यहाँ एक त्वरित और आसान स्पष्टीकरण है।
String
- एक बढ़ने योग्य, हीबल हीप-आवंटित डेटा संरचना। यह एक करने के लिए मजबूर किया जा सकता है &str
।
str
- (अब, जैसा कि जंग विकसित होती है) उत्परिवर्तित, निश्चित-लंबाई वाली स्ट्रिंग है जो ढेर पर या बाइनरी में रहती है। आप केवल str
एक स्ट्रिंग स्लाइस दृश्य के माध्यम से उधार के प्रकार के साथ बातचीत कर सकते हैं , जैसे कि &str
।
उपयोग के विचार:
पसंद करें String
यदि आप किसी स्ट्रिंग को स्वयं करना या म्यूट करना चाहते हैं - जैसे कि स्ट्रिंग को किसी अन्य थ्रेड को पास करना, आदि।
&str
यदि आप किसी स्ट्रिंग का केवल पढ़ने के लिए दृश्य चाहते हैं, तो उसे प्राथमिकता दें।
&str
दो घटकों से बना है: कुछ बाइट्स के लिए सूचक है, और लंबाई।"