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中,數據可以存儲在堆疊或堆記憶體中。

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

堆記憶體: 堆記憶體是有組織的記憶體。 操作系統在堆記憶體中找到一個空的空格並返回一個指針。 此過程稱為“在堆上分配”。

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

下麵來看一個簡單的記憶體分配示例。

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

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

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

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

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

使用複製特徵

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

以下是一些複製類型:

  • 所有整數類型,如u32
  • 布爾類型-bool,其值為truefalse
  • 所有浮動類型,如f64
  • 字元類型,如char

所有權和函數

當變數傳遞給函數時,所有權將移動到被調用函數的變數。 傳遞值的語義等於為變數賦值。

下麵通過一個例子來理解這一點:

fn main()
{
  let s=String::from("zaixian");
  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);
}

執行上面示例代碼,得到以下結果 -

zaixian
a
a

在上面的例子中,字串s與值zaixian綁定,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變數。


上一篇: Rust while迴圈 下一篇: Rust引用和借用