所有权是Rust程式设计语言提供的独特功能,可在不使用垃圾收集器或指标的情况下提供记忆体安全保障。
当程式码块拥有资源时,它被称为所有权。程式码块建立一个包含资源的物件。当控制元件到达块的末尾时,物件将被销毁,资源将被释放。
所有权的重点:
- 「所有者」可以根据可变性改变变数的拥有值。
- 所有权可以转移到另一个变数。
- 所有权只是在Rust中移动语意。
- 所有权模型也保证了并行的安全性。
所有权规则
- 在Rust中,每个值都有一个与之关联的变数,并称为其所有者。
- 一次只能有一个所有者。
- 当所有者超出范围时,与其关联的值将被销毁。
所有权的例子
多个变数可以在Rust中相互互动。下面来看一个例子:
将x``y
let x=10;
let y=x;
在上面的例子中,然后,在这种情况下,不会建立 因此,如果尝试重用变数 可通过下面的例子来理解这一点。x``10``x``y``x``x``y``x``y``x``x
fn main()
{
let x=10;
let y=x;
println!("value of x :{}",x);
}
编译上面程式码,范例的输出如下:
在Rust中,资料可以储存在堆叠或堆记忆体中。
堆叠储存器:它遵循「后进先出」的原则,即始终首先删除最后插入的资料。堆叠记忆体是一种有组织的记忆体。它比堆记忆体更快,因为它存取记忆体的方式。如果在编译时资料的大小未知,则堆记忆体用于储存内容。
堆记忆体:作业系统在堆记忆体中找到一个空的空格并返回一个指标。此过程称为「在堆上分配」。
此图显示堆叠包含指标,而堆包含内容。
下面来看一个简单的记忆体分配范例。
fn main()
{
let v1=vec![1,2,3];
let v2=v1;
}
第1步:向量由三部分组成,即指向储存器中指向储存在记忆体中的资料的指标,长度和向量的容量。这些部分储存在堆叠中,而资料储存在堆记忆体中,如下所示:
v1``1``2``3
第2步:指标,长度和容量将复制到堆叠中,但不会将资料复制到堆记忆体中。现在记忆体的表示如下:
v1``v2
但是,这种表示形式可能会产生问题。当 这会导致双重空闲记忆体,这会导致记忆体损坏。v1``v2
第3步:Rust没有复制分配的记忆体,而是认为 因此,当
v1``v1``v1
复制特征是一种特殊的注释,它放在储存在堆叠上的整数型别上。如果在型别上使用了复制特征,则即使在赋值操作之后也可以进一步使用旧变数。
以下是一些复制型别:
- 所有整数型别,如
u32
- 布林型别-
bool``true``false
- 所有浮动型别,如
f64
- 字元型别,如
char
当变数传递给函式时,所有权将移动到被呼叫函式的变数。传递值的语意等于为变数赋值。
下面通过一个例子来理解这一点:
fn main()
{
let s=String::from("Yiibai");
take_ownership(s);
let ch='a';
moves_copy(ch);
println!("{}",ch);
}
fn take_ownership(str:String)
{
println!("{}",str);
}
fn moves_copy(c:char)
{
println!("{}",c);
}
执行上面范例程式码,得到以下结果 -
Yiibai
a
a
在上面的例子中,字串 变数与值 之后也可以使用s``Yiibai``s``take_ownership()``str``ch``a``ch``moves_copy()``c``ch
从函式返回值也会转移所有权。看看这个范例:
fn main()
{
let x= gives_ownership();
println!("value of x is {}",x);
}
fn gives_ownership()->u32
{
let y=100;
y
}
执行上面范例程式码,得到以下结果 -
value of x is 100
在上面的例子中,give_ownership()``y``100``y``x