Rust基礎(chǔ)之變量、元組、數(shù)據(jù)、函數(shù)、遮蔽、復(fù)制、可變引用、不可變引用


fn main() {

? ? log("varible");

? ? let v_x:i32=5;

? ? let v_y:String="test".to_string();

? ? let v_z:char='a';

? ? let v_a:bool=true;

? ? let v_b:f64=3.14;

? ? const PI:f64=3.1415926;

? ? let v_t:bool=true;

? ? println!("int:{v_x},str:{v_y},char:{v_z},bool:{v_a},float:{v_b},const:{PI},bool:{v_t}");

? ? log("shawdowing");

? ? let s_x=5;

? ? {

? ? ? ? let s_x:i32=s_x*2;

? ? ? ? //作用域內(nèi)的x值只在作用域內(nèi)生效,會遮蔽作用域外的x,當(dāng)該作用域結(jié)束,域內(nèi)的x被使用,遮蔽結(jié)束

? ? ? ? println!("shadowing x:{s_x}");

? ? }

? ? println!{"actual x:{s_x}"}

? ? //元組用于存放類型不一致的一組數(shù)據(jù),使用.操作符訪問元組成員,也可使用解構(gòu)函數(shù)訪問元組成員;數(shù)組用于存放一組類型一致的數(shù)據(jù),使用下標訪問數(shù)組元素

? ? log("tuple array");

? ? let tup:(i32,f64,bool)=(3,3.14,true);

? ? let (t1,t2,t3)=tup;

? ? let arr=[1,2,3,4,5];

? ? let arr1:[i32;5]=[1,2,3,4,5];

? ? println!("tup.0:{},t1:{},t2:{},t3:{},arr[0]:{},arr1[0]:{}",tup.0,t1,t2,t3,arr[0],arr1[0]);

? ? //函數(shù)與其他編程語言類似

? ? log("function");

? ? println!("add:{}",add(3,5));

? ? let ?f_x=5;

? ? println!("x before function:{}",f_x) ;

? ? change_number(f_x);

? ? println!("x after function:{}",f_x) ;

? ? let f_s:String=String::from("string ");

? ? println!("str before function:{}",f_s) ;

? ? //實參如果是string類型,必須傳入String的復(fù)制體,因為String不能自動復(fù)制,會發(fā)生所有權(quán)轉(zhuǎn)移,傳入函數(shù)后,原變量會失效

? ? change_str(f_s.clone());

? ? //若上一句不傳入clone()復(fù)制體,以下語句將報錯。

? ? println!("{f_s}"); ?

? ? // rust中每一個值都擁有一個所有者

? ? // 每一個個值在任意一個時刻有且只能有一個所有者

? ? // 當(dāng)值的所有者離開作用域,該值將會被丟棄,內(nèi)存會被回收

? ? //copy

? ? log("copy");

? ? let c_x=5;

? ? let c_y=c_x;

? ? println!("x:{},y:{}",c_x,c_y);

? ? // move

? ? log("move");

? ? let c_str:String=String::from("Move String");

? ? let c_str1=c_str;

? ? //println!("c_str:{}",c_str); c_str會被丟棄,因為指向該字符串值的指針已被轉(zhuǎn)移至c_str1

? ? println!("c_str1:{}",c_str1);

? ? // 當(dāng)你復(fù)制一個字符串字面量時,原字符串字面量仍然可用,因為字符串字面量是存儲在棧上的大小已知的數(shù)據(jù)類型,與整形等類似,復(fù)制棧數(shù)據(jù)并不會消耗資源,唯一的缺點是不可變

? ? log("copy &str");

? ? let c_stra="c_stra";

? ? let ?c_strb=c_stra;

? ? println!("c_stra:{c_stra}");

? ? println!("c_strb:{c_strb}");

? ? log("copy String");

? ? // 當(dāng)你將一個字符串變量賦值給一個新的變量時,該字符串變量會失效,因為其是存儲在堆上

? ? //復(fù)制該變量會將保存變量指針的地址轉(zhuǎn)移至新變量,為確保不會發(fā)生二次釋放,舊變量必須失效,除非使用clone生成一個該變量的深復(fù)制,唯一的缺點是clone相當(dāng)消耗資源。

? ? {

? ? ? ? let str=String::from("owner_ship");

? ? ? ? let str1=str;

? ? ? ? //println!("{o_str}"); 這里不能使用o_str1 因為其所有權(quán)被轉(zhuǎn)移,已失效

? ? ? ? println!("o_str1:{str1}");

? ? }

? ? log("reference");

? ? {

? ? ? ? //對各類變量的操作將會導(dǎo)致大量的所有權(quán)轉(zhuǎn)移和變更,比較繁瑣

? ? ? ? let r_str:String=String::from("Move String");

? ? ? ? //println!("r_str:{}",r_str); 該語句將報錯,因為下一句已經(jīng)將r_str所有權(quán)轉(zhuǎn)移至calc_len函數(shù)內(nèi),r_str將被丟棄

? ? ? ? let (s,l)=calc_len(r_str);

? ? ? ? println!("r_str:{},length:{}",s,l);

? ? }

? ? //引用, 在不獲得所有權(quán)的情況下使用數(shù)據(jù),分為可變引用和不可變引用

? ? {

? ? ? ? //不可變引用,一個作用域內(nèi)可以同時存在一個變量的多個不可變引用,不會有額外性能開銷

? ? ? ? //以上計算字符串長度的函數(shù)可以在不獲取原字符串所有權(quán)的前提下,使用引用實現(xiàn)

? ? ? ? let r_str:String=String::from("unmutable Reference String ");

? ? ? ? let l=calc_len_by_reference(&r_str);

? ? ? ? println!("length of r_str1:{}",l);

? ? }

? ? {

? ? ? ? //一個作用域內(nèi)可存在多個不可變引用,因為不可變引用沒有所有權(quán),不會發(fā)生數(shù)據(jù)競爭

? ? ? ? let r_str:String=String::from("unmutable Reference String ");

? ? ? ? let r_str1:&String=&r_str;

? ? ? ? let r_str2:&String=&r_str;

? ? ? ? let r_str3:&String=&r_str;

? ? ? ? println!("r_str:{},r_str1:{},r_str2:{},r_str3:{}",r_str,r_str1,r_str2,r_str3);

? ? ? ? //不可變引用的缺點是所有的引用都不可變,因為不可變引用不具有所有權(quán)

? ? ? ? //取消注釋以下代碼將報錯

? ? ? ? //r_str3.push_str("string");

? ? }

? ? {

? ? ? ? //可變引用,可以使用可變引用去改變一個變量

? ? ? ? let mut r_str:String=String::from("mutable Reference String ");

? ? ? ? println!("可變引用改變前的r_str2:{}",r_str);

? ? ? ? change_str_by_mut_reference(&mut r_str);

? ? ? ? println!("可變引用改變后的r_str2:{}",r_str);

? ? }

? ? {

? ? ? ? //一個作用域內(nèi)僅可擁有一個可變引用,同時存在多個可變引用將會引起數(shù)據(jù)競爭或引發(fā)內(nèi)存污染

? ? ? ? let mut r_str:String=String::from("mutable Reference String");

? ? ? ? let _r_str1: &mut String=&mut r_str;

? ? ? ? //取消注釋以下代碼將報錯

? ? ? ? //let _r_str2: &mut String=&mut r_str2;

? ? ? ? //println!("length of r_str1:{},{}",_r_str1,_r_str2);

? ? }

? ? {

? ? ? ? //一個作用域內(nèi)不能同時存在可變引用和不可變引用

? ? ? ? let mut _r_str:String=String::from("mutable Reference String");

? ? ? ? let _r_str1: &mut String=&mut _r_str;

? ? ? ? //取消注釋以下代碼將報錯,因為已存在不可變引用,不可以創(chuàng)建可變引用,因為一個作用域內(nèi)任何不可變引用存在時,其所有者都不希望該引用的值發(fā)生變化

? ? ? ? //let _r_str2: &String=&_r_str;

? ? ? ? //println!("{}, {}", _r_str1, _r_str2);

? ? ? ? //在不同的作用域內(nèi)可以存在多個對一個變量的可變引用

? ? ? ? {

? ? ? ? ? ? let _r_str3: &mut String=&mut _r_str;

? ? ? ? ? ? println!("mutable reference _r_str3:{}", _r_str3);

? ? ? ? }

? ? }

? ? log("懸垂引用 dangling pointer");

? ? {

? ? ? ? //取消注釋以下語句將會報錯,因為函數(shù)內(nèi)返回str 的引用,但函數(shù)結(jié)束時,函數(shù)內(nèi)的str被釋放,返回的引用變成懸垂引用,

? ? ? ? //let str=dangle();

? ? ? ? //fn dangle()->&String{

? ? ? ? ? ? //let str=String::from("dangling string");

? ? ? ? ? ? //&str

? ? ? ?// }

? ? }

? ? {

? ? ? ? //避險懸垂引用的辦法時直接返回變量,是變量所有權(quán)轉(zhuǎn)移至函數(shù)外變量

? ? ? ? let _str=dangle1();

? ? }

}

fn dangle1()->String{

? ? let str=String::from("dangling string");

? ? str

}

fn calc_len(s:String)->(String,usize){

? ? let l: usize=s.len();

? ? return (s,l);

}

fn calc_len_by_reference(s:&String)->usize{

? ? s.len()

}

fn change_str_by_mut_reference( s: &mut String){

? ? s.push_str("muteed");

}

fn add(x:i32,y:i32)->i32{

? ? x+y

}

fn change_number(mut i:i32){

? ? i=i+1;

? ? println!("x in function:{}",i) ;

}

fn change_str(mut s:String){

? ? s.push_str("pushed");

? ? println!("str in function:{}",s) ;

}

fn log(s:&str){

? ? println!("################## {s} ##################");

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容