













let codition = true;
let x = if condition {5} else {6};
fn five()->i32 {
5
}
fn main(){
let x= five();
println!("The value of x is: {x}");
}
let result = loop{
break 5;
}
'my_loop_label loop{
loop{
break 'my_loop_label;//直接结束外层循环
}
}
let array = [1,2,3,4];
for element in array{
println("element is {element}");
}
for element in (1..5).rev(){
println("{element}");//打印出4 3 2 1
}
Box的所有者来管理堆内存释放
Rust会自动释放Box的堆内存
Rust内存释放机制
如果一个变量拥有一个Box(即该Box的所有权人是这个变量且仅是这个变量),当rust释放变量的frame(栈桢)时,Rust也会释放Box的堆(Heap)内存
Rust中,像Vec、String、HashMap等集合类型,都使用了Box
移动堆数据原则(所有权转移原则)
如果一个变量x将堆内存Heap所有权转移给另一个变量y,那么在移动后,变量x就不能再使用。
使用 "&" 符号加变量名的方式,用在函数形参中,这就是表示要为该函数传递一个引用类型的参数。引用是没有所有权的。
注意下图中,引用的本质,引用g1,g2指向了拥有所有权的变量m1,m2上,并不是直接指向堆。所以当引用超出作用范围时,并不会释放堆内存。

let a = String::from("Hello");
let reference_a = &a;
let address_in_reference_a = reference_a as *const String;
println!("a:{}",a);
println!("&a{{:p}},即变量a在Stack上的内存地址:{:p}",&a);
println!("reference_a:{}",reference_a);
println!("address_in_reference_a{{:p}},即reference_a的值的内容:{:p}",address_in_reference_a);
println!("&reference_a{{:p}},即变量reference_a在Stack上的内存地址:{:p}",&reference_a);
以下为输出结果:
a:Hello
&a{:p},即变量a在Stack上的内存地址:0x9bab8ff858
reference_a:Hello
address_in_reference_a{:p},即reference_a的值的内容:0x9bab8ff858
&reference_a{:p},即变量reference_a在Stack上的内存地址:0x9bab8ff870
let m = String::from("hello world");
println!("{}",m);
println!("{}",&m);
println!("{}",&&m);
解引用指针以方问数据,解引用运算符:* 看下图:

Rust中经常在【成员.方法名()】的用法中进行隐式的引用或解引用,看下图:

别名(堆内存的无所有权的直接引用者)和可变性不可同时存在(本质的意思是说不允许某个引用修改了它指向的堆上的数据但别的引用却不知道。避免空指针、保障线程安全)
换句话说:数据不应同时被别名引用而又具有可变性
比如下图阐述了一段会造成空指针问题的代码:

但是,可以通过间接方式(注意,这和别名引用不同),把变量(指向堆内存的)的引用赋给多个变量的方式来间接让多个变量访问同一块堆内存数据并且原变量还具有可变性,比如下图代码:


下面是一个数据在被创建引用时,各变量自动获得和失去三种权限的一个动态变化情况:
在创建了另一个别名num后数,v同时失去了W和O的权限,只保留了R的权限。在打印那一语句执行完后,num及*num随即失去了三种权限,同时三种权限归还给了变量v。
而最后一行执行完后,当数据不再被后面代码使用到,则v立即失去三种权限,一旦数据所有者变量v失去数据所有权,则栈内存被释放的同时堆上的数据也被立即释放。个人体会:这种设计得以堆内存的数据随时为被释放做好准备,体现了Rust是高性能的语言高在了哪里。

以又是一个示例演练。

猜想:在执行完第二个语句后,x会重新获得堆数据的所有权,但是如果这之后没有再引用到变量x,则x同时会被释放栈和它指向的堆上的数据的内存。
比如:变量、解引用、数组元素、元组和结构体的成员访问,以及它们的组合比如:*((*a)[0].field1)
(个人理解不如把它们统称为“数据访问者”,它引发自己或其他数据访问者权限状态改变的改变 Trigger)
为什么随者位置的不再使用,“位置”会失去所有权?因为权限是互斥的。(个人阐述为随者数据访问者的先后触发权限改变,后触发者会改变前面触发者的权限状态,有时就是让前面触发者失去某些权限)如下图:

借用检查器能发现权限违规。Rust在借用检查器里使用RWO等权限。借用检查器查找涉及引用的潜在不安全操作。下图简单示意了借用检查器的工作原理:

可变引用可能会临时降级为只读,如下图:

权限在引用生命周期结束时被返回,如下图:

如果有if else等分支控制语句,也是这样,一个引用生命周期开始和结束,都会影响到期他数据访问者的权限:

以下代码一和代码二,其函数无法通过编绎,提示缺少生命周期说明符。
代码一:(以下代码,从函数的两个输入参数无法确定函数的返回值的生命周期【一般情况下,出参和入参生命周期一致】)

代码二:(因为按照前面所学,在函数返回时a早已经超出生命周期而被释放了)
fn return_a_string()->&String{
let a = String::from("hello");
let b = &a;
return b;
}
代码三:(n是分配在栈上的值类型变量,在incr函数内部,m会在栈上创建,其值为n的地址,*m即对m解引用的结果就是n的值。该代码最终输出2)
fn incr(m: &mut i32) {
*m += 1;
}
let mut n=1;
incr(&mut n);
println!("{}",n);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。