Rust 所有权

Rust 所有权

程序的内存可以分配在以下几个地方:

  • 栈(Stack)
  • 堆(Heap)

栈遵循先进后出的顺序。栈用于存储在编译时大小已知的数据值。例如,大小固定的i32类型的变量可以在栈上分配,因为其大小在编译时已知。所有标量类型都可以存储在栈上,因为大小是固定的。

考虑一个字符串的示例,在运行时给它赋值。这样的字符串的确切大小在编译时无法确定。因此,它不适合在栈上分配,而适合在堆上分配。

堆存储在编译时大小未知的数据值。它用于存储动态数据。简单地说,堆内存分配给可能在程序生命周期内发生变化的数据值。与栈相比,堆的组织结构较不规整。

什么是所有权

Rust中的每个值都有一个称为“所有者”的变量。Rust中存储的每个数据都有一个与之关联的所有者。例如,在以下语法中:
let age = 30,age是值30的所有者。

  • 每个数据一次只能有一个所有者。
  • 两个变量不能指向同一个内存位置。这些变量将始终指向不同的内存位置。

转移所有权

可以通过以下方式转移值的所有权:

  • 将一个变量的值赋给另一个变量。
  • 将值传递给函数。
  • 从函数中返回值。

将一个变量的值赋给另一个变量

Rust作为一种语言的一个主要卖点是其内存安全性。通过对谁可以在什么时候使用限制的严格控制来实现内存安全。

考虑以下代码片段:

fn main(){
   let v = vec
![1,2,3]; 

   // vector v owns the object in heap

   //only a single variable owns the heap memory at any given time
   let v2 = v; 
   // here two variables owns heap value,
   //two pointers to the same content is not allowed in rust

   //Rust is very smart in terms of memory access ,so it detects a race condition
   //as two variables point to same heap

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

上面的示例声明了一个向量v。所有权的概念是只有一个变量绑定到资源,要么是v绑定到资源,要么是v2绑定到资源。上面的示例抛出了一个错误 – 使用了转移的值:v。这是因为资源的所有权转移到了v2。这意味着所有权从v转移到了v2(v2=v),并且在转移之后,v将无效。

将值传递给函数

当我们将堆中的一个对象传递给闭包或函数时,值的所有权也会发生变化。

fn main(){
   let v = vec
![1,2,3];     // vector v owns the object in heap

   let v2 = v;              // moves ownership to v2
   display(v2);             // v2 is moved to display and v2 is invalidated
   println!("In main {:?}",v2);    //v2 is No longer usable here
}
fn display(v:Vec<i32>){
   println!("inside display {:?}",v);
}

从函数返回值

传递给函数的所有权在函数执行结束时将失效。其中一个解决方法是让函数将所有权的对象返回给调用者。

fn main(){
   let v = vec
![1,2,3];       // vector v owns the object in heap

   let v2 = v;                // moves ownership to v2
   let v2_return = display(v2);    
   println!("In main {:?}",v2_return);
}
fn display(v:Vec<i32>)->Vec<i32> { 
   // returning same vector
   println!("inside display {:?}",v);
}

所有权和基本类型

对于基本类型,一个变量的内容被复制到另一个变量中。所以,没有发生所有权转移。这是因为一个基本类型变量需要比一个对象更少的资源。考虑以下示例 –

fn main(){
   let u1 = 10;
   let u2 = u1;  // u1 value copied(not moved) to u2

   println!("u1 = {}",u1);
}

输出将为 -10。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程