[英]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
分配i32
, Box
將原始指針保存到堆分配的內存中。 請注意, Box
直接(內部的原始指針)直接在堆棧上,而不是在堆上! 只是i32
在堆上。
當Box
被移動時,就像我剛剛說的那樣,它被memcpy
。 這意味着堆棧內容被復制(!!)...因此只需逐個字節地復制指針。 沒有i32
的第二個版本!
在物理移動方面, Copy
和非Copy
類型之間沒有區別。 唯一的區別是編譯器對這些類型強制執行不同的規則。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.