Rust所有權

所有權是Rust編程語言提供的獨特功能,可在不使用垃圾收集器或指針的情況下提供內存安全保障。

什麼是所有權?

當代碼塊擁有資源時,它被稱爲所有權。 代碼塊創建一個包含資源的對象。 當控件到達塊的末尾時,對象將被銷燬,資源將被釋放。

所有權的重點:

  • 「所有者」可以根據可變性改變變量的擁有值。
  • 所有權可以轉移到另一個變量。
  • 所有權只是在Rust中移動語義。
  • 所有權模型也保證了並行的安全性。

所有權規則

  • 在Rust中,每個值都有一個與之關聯的變量,並稱爲其所有者。
  • 一次只能有一個所有者。
  • 當所有者超出範圍時,與其關聯的值將被銷燬。

所有權的例子

多個變量可以在Rust中相互交互。 下面來看一個例子:

x的值賦給變量y

let x=10;  
let y=x;

在上面的例子中,x綁定到值10。然後,x的值被賦給變量y。 在這種情況下,不會創建x的副本,而是將x的值移動到變量y。 因此,x的所有權被轉移到變量y,並且變量x被銷燬。 如果嘗試重用變量x,那麼Rust會拋出一個錯誤。可通過下面的例子來理解這一點。

fn main()  
{
    let x=10;  
    let y=x;  
    println!("value of x :{}",x);
}

編譯上面代碼,示例的輸出如下:

Rust所有權

內存和分配

在Rust中,數據可以存儲在堆棧或堆內存中。

Rust所有權

堆棧存儲器: 在堆棧存儲器中,數據始終按順序放置並以相反的順序移除。 它遵循「後進先出」的原則,即始終首先刪除最後插入的數據。 堆棧內存是一種有組織的內存。 它比堆內存更快,因爲它訪問內存的方式。 如果在編譯時數據的大小未知,則堆內存用於存儲內容。

堆內存: 堆內存是有組織的內存。 操作系統在堆內存中找到一個空的空格並返回一個指針。 此過程稱爲「在堆上分配」。

Rust所有權

此圖顯示堆棧包含指針,而堆包含內容。

下面來看一個簡單的內存分配示例。

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

第1步:
在程序的第一個語句中,向量v1與值1,23綁定。向量由三部分組成,即指向存儲器中指向存儲在內存中的數據的指針,長度和向量的容量。 這些部分存儲在堆棧中,而數據存儲在堆內存中,如下所示:

Rust所有權

第2步:
在程序的第二個語句中,將v1向量分配給向量v2。 指針,長度和容量將複製到堆棧中,但不會將數據複製到堆內存中。現在內存的表示如下:

Rust所有權

但是,這種表示形式可能會產生問題。 當v1v2都超出範圍時,兩者都會嘗試釋放內存。 這會導致雙重空閒內存,這會導致內存損壞。

第3步:
Rust避免了第2步 條件以確保內存安全。 Rust沒有複製分配的內存,而是認爲v1向量不再有效。 因此,當v1超出範圍時,它不需要釋放v1的內存。
Rust所有權

使用複製特徵

複製特徵是一種特殊的註釋,它放在存儲在堆棧上的整數類型上。 如果在類型上使用了複製特徵,則即使在賦值操作之後也可以進一步使用舊變量。

以下是一些複製類型:

  • 所有整數類型,如u32
  • 布爾類型-bool,其值爲truefalse
  • 所有浮動類型,如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()函數傳遞給變量strch變量與值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的值,即100y變量的所有權被轉移到x變量。