簡體   English   中英

Rust如何移動不可復制的堆棧變量?

[英]How does Rust move stack variables that are not Copyable?

這里記錄了Rust的移動語義的一個很好的例子:在Rust By Example網站上的Rust Move Semantics

我對兩個案例都有基本的了解。 第一個是原語如何擁有一個新的別名,原始的仍然可以使用,因為最終結果是一個副本,因為i32使用了Copy特征。 這對我來說很有意義。

此外,由於許多充分的理由,第二個示例在具有多個引用堆上的i32別名方面是i32的。 Rust強制執行所有權規則,因此現在無法使用原始別名創建新綁定。 這有助於防止數據爭用,雙重釋放等。

但似乎還有第三個案例沒有被談到。 Rust如何實現堆棧分配結構的移動,這些結構沒有實現Copy特征? 使用以下代碼對此進行說明:

#[derive(Debug)]
struct Employee{
    age: i32,
}

fn do_something(m: Employee){
    println!("{:?}", m);
}

fn main() {
    let x = Employee {
        age: 25,
    };

    do_something(x);

    //compiler error below because x has moved
    do_something(x);
}

我知道:在上面的例子中, Rust將在堆棧上分配Employee 上述結構不實現Copy特征 ,因此在分配給新別名時不會被復制。 這對我來說非常困惑,因為如果在堆棧上分配Employee結構並且還沒有實現Copy trait where / how如何移動? 它是否實際上被移動到do_something()的堆棧幀?

在解釋這個難題時,任何幫助都會受到贊賞。

它是否實際上被移動到do_something()的堆棧幀?

是。 Copy類型的物理移動方式與Copy類型完全相同:使用memcpy 您已經了解原始Copy -types Copy逐字節地復制到新位置(例如,新的堆棧幀)。

現在考慮Box這個實現:

struct Box<T> {
    ptr: *const T,
}

當你有

let b = Box::new(27i32);
do_something(b);    // `b` is moved into `do_something`

然后在i32分配i32Box將原始指針保存到堆分配的內存中。 請注意, Box直接(內部的原始指針)直接在堆棧上,而不是在堆上! 只是i32在堆上。

Box被移動時,就像我剛剛說的那樣,它被memcpy 這意味着堆棧內容被復制(!!)...因此只需逐個字節地復制指針。 沒有i32的第二個版本!

在物理移動方面, Copy和非Copy類型之間沒有區別。 唯一的區別是編譯器對這些類型強制執行不同的規則。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM