Rustda ikki xil satrlar mavjud: “String” va “&str”. Xo’sh ular orasidagi farq qanday ?
- &str bu oddiy satr hisoblanadi. Biz “
let my_variable = "Hello, world!"deb yozganimizda odatda &str yaratgan bo’lamiz va uni yaratish juda tez. - “String” esa biroz qiyinroq satr hisoblanadi.U ozgina sekinroq lekin ko’proq funksiyaga ega. “String” bu heap da joylashgan ma’lumotimiz uchun ko’rsatgich(pointer) hisoblanadi.
Bir narsani e’tiborga olishimiz kerakki, “&str” o’zidan oldin & bilan keladi sababi biz str dan foydalanishimiz uchun “reference” kerak bo’ladi. Bunga sabab, oldingi postda aytib o’tgan stack ning talabi, y’ani aniq hajmni oldindan bilish. Shuning uchun ham hajmini bildirish uchun biz & dan foydalanamiz.Undan tashqari, “String” dan farqli o’laroq &str ni & bilan ishlatganimiz uchun ham biz unga egalik qilmaymiz, ya’ni reference bo’ladi.
&str va “String” ham UTF8 hisoblanadi. Misol uchun:
fn main() {
let name = "서태지"; // Bu yerda biz &str ishlatayapmiz va koreys tilidagi ismlarni ham chop eta olamiz
let other_name = String::from("Adrian Fahrenheit Țepeș"); // Ț va ș ham muammo emas chop etishga
}
Ko’rib turganingizdek String::from("Adrian Fahrenheit Țepeș") &str dan “String” yaratish juda ham oson. Bu ikki ma’lumot turi bir biriga juda ham bog’langan.
Ular UTF-8 bo’lgani hisobiga biz emojilar ham yoza olamiz.
fn main() {
let name = "😂";
println!("My name is actually {}", name);
}
Ushbu kod ishga tushirilganda My name is actually 😂 natija ko’rsatilishi kerak, agar ishlatayotgan terminalingiz/console emojilarni chop eta olmasa unda, My name is actually � ko’rishingiz ham mumkin. Lekin Rust da emojilar bilan ishlashda muammoga duch kelmaymiz.
Endi yanada tushunish uchun, nega “str” bilan & ni qo’llayotganimizga to’xtalib o’tsak.
- “str” bu dinamik o’lchamdagi ma’lumot turi hisoblanadi.ya’ni uning,boshqa ma’lumot turlariga o’xshab, oldindan belgilab qo’yilgan o’lcham hajmi yo’q. Misol uchun “서태지” va “Adrian Fahrenheit Țepeș” bir xil o’lchamda emas.
fn main() {
println!("A String is always {:?} bytes. It is Sized.", std::mem::size_of::<String>()); // std::mem::size_of::<Type>() ma'lumot turining byte dagi hajmini beradi
println!("And an i8 is always {:?} bytes. It is Sized.", std::mem::size_of::<i8>());
println!("And an f64 is always {:?} bytes. It is Sized.", std::mem::size_of::<f64>());
println!("But a &str? It can be anything. '서태지' is {:?} bytes. It is not Sized.", std::mem::size_of_val("서태지")); // std::mem::size_of_val() o'zgaruvchining byte dagi o'lchamini beradi
println!("And 'Adrian Fahrenheit Țepeș' is {:?} bytes. It is not Sized.", std::mem::size_of_val("Adrian Fahrenheit Țepeș"));
}
A String is always 24 bytes. It is Sized.
And an i8 is always 1 bytes. It is Sized.
And an f64 is always 8 bytes. It is Sized.
But a &str? It can be anything. '서태지' is 9 bytes. It is not Sized.
And 'Adrian Fahrenheit Țepeș' is 25 bytes. It is not Sized.
Shuning uchun ham biz “&” ishlatamiz. Sababi Rust ko’rsatgichning(pointer) hajmini biladi va & bizga aynan shu ko’rsatgichni yaratishimizda yordam beradi. Undan keyin esa bu ko’rsatgich “Stack” ga qo’shiladi. Agar & ishlatmaganimizda, Rust biz kiritayotgan “str” bilan nima qilishni bilmay qolardi sababi uning hajmi oldindan ma’lum bo’lmaydi va bu standardlarga zid.
“String” yaratishning juda ham ko’p turlari bor:
String::from("This is the string text");Bu shaklda kiritilgan matn orqali String yaratiladi."This is the string text".to_string(). Bu metod orqali biz &str ni String ko’rinishiga o’tkazamiz.- “format!” makrosi. Bu ham huddi “println!” ga o’xshaydi lekin chop etishni o’rniga bizga “String” yaratishga yordam beradi.
fn main() {
let my_name = "Billybrobby";
let my_country = "USA";
let my_home = "Korea";
let together = format!(
"I am {} and I come from {} but I live in {}.",
my_name, my_country, my_home
);
}
Ushbu kodda biz “format!” orqali “together” deb nomlangan “String” turdagi o’zgaruvchi yaratdik.
“String” yaratishning yana bir yo’llaridan biri bu “.into()”, lekin bu tepada keltirib o’tgan uslublarimizdan sal boshqacharoq. Sababi “.into()” faqatgina “String” uchungina ishlatilmaydi. Ba’zi bir ma’lumot turlarini “From” va “.into()” orqali osongina bir turdan ikkinchi turga o’tkazish mumkin. “From” ni qo’llaganda, bu ancha tushunarli sababi biz konvertatsiya qilmoqchi bo’lgan o’zgaruvchimizning ma’lumot turini bilamiz, misol uchun String::from("Some str"). Bu yerda qavs ichidagi qiymat &str ekanligi bizga ma’lum va biz undan “String” yaratayapmiz. Lekin “.into()” bilan ishlatganda, kompilyator ba’zi vaqtlar ma’lumot turini bilmay qoladi.
fn main() {
let my_string = "Try to make this a String".into(); // ⚠️
}
Bu kodda xatolik beradi, sababi Rust aynan qaysi turga konvertatsiya qilmoqchiligingizni bilmaydi. Negaki odatiy “&str” dan juda ham ko’p turdagi ma’lumotlarga konvertatsiya qilsak bo’ladi.
error[E0282]: type annotations needed
--> src\main.rs:2:9
|
2 | let my_string = "Try to make this a String".into();
| ^^^^^^^^^ consider giving `my_string` a type
Ushbu xatolikni to’g’irlash uchun biz o’zgaruvchimizga aniq ma’lumot turini kiritsak kifoya:
fn main() {
let my_string: String = "Try to make this a String".into();
}
ana endi bu kod ishlaydi va bizga “&str” ni “String” ko’rinishiga o’tkazib beradi.
Leave a Reply