【问题标题】:Struct ownership结构所有权
【发布时间】:2020-10-16 14:24:11
【问题描述】:
struct Haha {
    pub a: u32,
    pub b: Vec<u32>,
}
let example = Haha {
    a: 32,
    b: vec![1],
}; 
let new_a = example.a;
let new_b = example.b;

我的理解是:

  1. new_aexample.a 的副本,所以 example 仍然拥有 example.a
  2. new_b 现在拥有 example.b,因为 example.b 已被移动。

rust 是否会隐式复制 example.a,因为它具有 Copy 特征?并且由于example.b,这是一个Vec,没有实现Copy trait,example.b 的所有权被移动而不是复制?

【问题讨论】:

  • 查看这篇博文medium.com/@bugaevc/…“幸运的是,Rust 具有 Copy trait。实现它的类型(所有原始类型都这样做)在分配时使用复制语义,所有其他类型都使用移动语义。 "

标签: rust ownership


【解决方案1】:

你的理解是正确的。 a 被复制,b 被移动。您可以稍后尝试访问这两个字段来确认这一点。

println!("{:?}", example.a);

这打印出32example.a 仍然可以访问,因为它是复制的,而不是移动的。

println!("{:?}", example.b);

访问example.b编译失败,报错:

error[E0382]: borrow of moved value: `example.b`
  --> src/main.rs:13:22
   |
12 |     let _new_b = example.b;
   |                  --------- value moved here
13 |     println!("{:?}", example.b);
   |                      ^^^^^^^^^ value borrowed here after move
   |
   = note: move occurs because `example.b` has type `std::vec::Vec<u32>`, which does not implement the `Copy` trait

这完全证实了你所说的,example.b 被移动是因为它没有实现 Copy 特征。

【讨论】:

  • 感谢您的快速回复!所以对于像我这样的 rust 新手(可能不知道 vec 没有实现复制特征),我们是否必须依赖编译器来检查所有权,因为复制是隐式完成的?
  • @LouisLee 您可以在API documentation 中看到一个类型是否为Copy
  • @LouisLee 如果在编译时知道变量的大小(例如 i32),则可以将其存储在堆栈中,因此可以快速复制。如果在编译时不知道变量的大小(例如向量),它将存储在堆中,并且指向堆中内存位置的指针存储在堆栈中。 Rust 不会在堆中复制内存,因为它速度慢且效率低。你可以假设如果一个变量正在使用堆,它就不会实现复制特征。
  • 我还有一个问题。我认为结构和枚举默认保存在堆栈中,除非某些字段必须在堆中分配。所以如果我这样做 ``` struct haha​​{ pub a: i32, pub b: inner } struct inner{ pub c: u32 } ``` 虽然我没有为 struct inner 派生复制或克隆特征,但我期待 struct内部要分配堆栈,但编译器告诉我它不是。那么结构是否存储在堆中,除非它们派生出复制特征?
  • @LouisLee 不,Rust 不会自动决定是在堆栈上还是在堆上分配东西。默认情况下,东西是在堆栈上分配的。某些结构(例如Vec)的实现方式是它们在堆上分配东西。只是做某事Copy 不会改变它是否分配在堆栈或堆上。
猜你喜欢
  • 2021-12-21
  • 2015-09-22
  • 2020-02-16
  • 2020-02-15
  • 1970-01-01
  • 2011-07-09
  • 2015-01-25
  • 1970-01-01
  • 2022-06-13
相关资源
最近更新 更多