作者:or70woo | 来源:互联网 | 2023-10-10 17:58
问题标题可能有点误导,因为我不知道如何正确表达我的意思。
这是问题所在。我有这段代码,它按预期工作。
enum Answer {
Yes,
No(i32),
}
pub struct QnA {
question: String,
answer: Answer,
}
fn check(qna: &QnA) {
match qna.answer {
Answer::Yes => println!("positive"),
Answer::No(why) => println!("negative cause {}", why),
}
}
我感兴趣的是那match
部分。假设我将枚举更改为Answer
这样的内容,
enum Answer {
Yes,
No(String),
}
比赛将不再有效。它说它不能移出引用后面的东西。为了使它工作,我必须&qna.answer
在比赛中使用引用。
我知道错误只发生在堆使用的类型上。所以我可以得到一个提示,这是因为所有权系统,但我无法直观地弄清楚枚举和结构之间的关系。我不知道枚举如何使用堆或堆栈处理其子类型。
回答
我知道错误只发生在堆使用的类型上。
这是不真实的。错误发生在没有实现的类型上Copy
,这意味着它们必须被移动。i32
和大多数其他原语实现Copy
,这意味着您可以自由地对引用进行模式匹配并隐式复制非引用值。但是,对于Copy
像 那样的非值String
,隐式复制不再发生,并且您尝试将值移出引用,这是不允许的。
看:
- Rust 编程语言:什么是所有权?
- Rust by example:所有权和移动
- Rust 文档:我的类型
Copy
什么时候可以是?(以及随后的“我的类型何时不能是Copy
?”和“我的类型何时应该是Copy
?”)
顺便提一下,Rust 的类型系统没有区分堆类型和堆栈类型,因为它们是不必要的区别。堆只是一块内存,就像某些内存分配器决定使用的堆栈一样,而在核心库中,没有堆分配器。通常,只有堆栈上的类型才能实现Copy
,因为这些类型复制起来很便宜,而堆内存必须重新分配。然而,这并不是说栈上的每个类型都实现了Copy
(你可以在栈上创建一个结构体而不在它上面实现 Copy),或者堆上没有类型实现Copy
(你可以有一个自定义的分配器或垃圾收集器) )。
I think that the OP confusion comes from the Book saying (in that chapter you link): "Rust has a special annotation called the Copy trait that we can place on types like integers that are stored on the stack". It seems to equal stack-allocated with `Copy`.