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;
//作用域内的x值只在作用域内生效,会遮蔽作用域外的x,当该作用域结束,域内的x被使用,遮蔽结束
println!("shadowing x:{s_x}");
}
println!{"actual x:{s_x}"}
//元组用于存放类型不一致的一组数据,使用.操作符访问元组成员,也可使用解构函数访问元组成员;数组用于存放一组类型一致的数据,使用下标访问数组元素
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]);
//函数与其他编程语言类似
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的复制体,因为String不能自动复制,会发生所有权转移,传入函数后,原变量会失效
change_str(f_s.clone());
//若上一句不传入clone()复制体,以下语句将报错。
println!("{f_s}");
// rust中每一个值都拥有一个所有者
// 每一个个值在任意一个时刻有且只能有一个所有者
// 当值的所有者离开作用域,该值将会被丢弃,内存会被回收
//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会被丢弃,因为指向该字符串值的指针已被转移至c_str1
println!("c_str1:{}",c_str1);
// 当你复制一个字符串字面量时,原字符串字面量仍然可用,因为字符串字面量是存储在栈上的大小已知的数据类型,与整形等类似,复制栈数据并不会消耗资源,唯一的缺点是不可变
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");
// 当你将一个字符串变量赋值给一个新的变量时,该字符串变量会失效,因为其是存储在堆上
//复制该变量会将保存变量指针的地址转移至新变量,为确保不会发生二次释放,旧变量必须失效,除非使用clone生成一个该变量的深复制,唯一的缺点是clone相当消耗资源。
{
let str=String::from("owner_ship");
let str1=str;
//println!("{o_str}"); 这里不能使用o_str1 因为其所有权被转移,已失效
println!("o_str1:{str1}");
}
log("reference");
{
//对各类变量的操作将会导致大量的所有权转移和变更,比较繁琐
let r_str:String=String::from("Move String");
//println!("r_str:{}",r_str); 该语句将报错,因为下一句已经将r_str所有权转移至calc_len函数内,r_str将被丢弃
let (s,l)=calc_len(r_str);
println!("r_str:{},length:{}",s,l);
}
//引用, 在不获得所有权的情况下使用数据,分为可变引用和不可变引用
{
//不可变引用,一个作用域内可以同时存在一个变量的多个不可变引用,不会有额外性能开销
//以上计算字符串长度的函数可以在不获取原字符串所有权的前提下,使用引用实现
let r_str:String=String::from("unmutable Reference String ");
let l=calc_len_by_reference(&r_str);
println!("length of r_str1:{}",l);
}
{
//一个作用域内可存在多个不可变引用,因为不可变引用没有所有权,不会发生数据竞争
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);
//不可变引用的缺点是所有的引用都不可变,因为不可变引用不具有所有权
//取消注释以下代码将报错
//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);
}
{
//一个作用域内仅可拥有一个可变引用,同时存在多个可变引用将会引起数据竞争或引发内存污染
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);
}
{
//一个作用域内不能同时存在可变引用和不可变引用
let mut _r_str:String=String::from("mutable Reference String");
let _r_str1: &mut String=&mut _r_str;
//取消注释以下代码将报错,因为已存在不可变引用,不可以创建可变引用,因为一个作用域内任何不可变引用存在时,其所有者都不希望该引用的值发生变化
//let _r_str2: &String=&_r_str;
//println!("{}, {}", _r_str1, _r_str2);
//在不同的作用域内可以存在多个对一个变量的可变引用
{
let _r_str3: &mut String=&mut _r_str;
println!("mutable reference _r_str3:{}", _r_str3);
}
}
log("悬垂引用 dangling pointer");
{
//取消注释以下语句将会报错,因为函数内返回str 的引用,但函数结束时,函数内的str被释放,返回的引用变成悬垂引用,
//let str=dangle();
//fn dangle()->&String{
//let str=String::from("dangling string");
//&str
// }
}
{
//避险悬垂引用的办法时直接返回变量,是变量所有权转移至函数外变量
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} ##################");
}
Rust基础之变量、元组、数据、函数、遮蔽、复制、可变引用、不可变引用
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 20240225Rust学习笔记 cargo build 编译并构建可执行文件 cargo run 编译并构建可执...
- github地址:https://github.com/bradyjoestar/rustnotes(欢迎star...