[英]Rust lifetimes for struct references
I've just started with Rust but can't quite grasp lifetimes so I could resolve following issue by myself: 我刚开始使用Rust,但是不能完全掌握一生,因此我可以自己解决以下问题:
This test project is about simulating a bit to allow tracing it through various bitwise operations, eg let newbit = oldbit1 ^ oldbit2
and looking at newbit
I can tell afterwards it came out of an XOR operation with oldbit1
and oldbit2
as operands. 该测试项目是关于模拟一个位以允许通过各种按位操作对其进行跟踪,例如, let newbit = oldbit1 ^ oldbit2
并查看newbit
之后,我可以分辨出它来自于以oldbit1
和oldbit2
作为操作数的XOR操作。
#[derive(Copy,Clone)]
pub enum TraceOperation {
AND,
OR,
XOR,
NOT,
}
#[derive(Copy,Clone)]
pub struct TraceBit<'a> {
source_a: Option<&'a TraceBit<'a>>,
source_b: Option<&'a TraceBit<'a>>,
source_op: Option<TraceOperation>,
value: bool,
}
This compiles, but I don't fully understand why the lifetime parameters are needed that way. 可以编译,但是我不完全理解为什么需要这种寿命参数。 I assume that the compiler cannot expect that the members source_a
and source_b
live as long as the struct itself as this may not hold true, so explicit lifetimes are required. 我假设编译器不能期望成员source_a
和source_b
生存,只要结构本身不成立即可,因此需要显式的生存期。
Further I don't fully understand why I have to re-specify the lifetime parameter for the reference type, ie why I have to write source_a: Option<&'a TraceBit<'a>>
as opposed to source_a: Option<&'a TraceBit>
. 此外,我不完全理解为什么我必须为引用类型重新指定生命周期参数,即为什么我必须编写source_a: Option<&'a TraceBit<'a>>
而不是source_a: Option<&'a TraceBit>
。
source_a
is a variable of type Option
that may have Some
reference (that is valid at least as long as the struct itself and as long as member source_b
) to an instance of TraceBit
" 我有:“ source_a
是Option
类型的变量,可能对TraceBit
实例具有Some
引用(至少在结构本身和成员source_b
) My final issue is that I cannot make it to work using an overloaded operator: 我的最后一个问题是我无法使用重载运算符来使其工作:
use std::ops::BitXor;
impl<'a> BitXor for TraceBit<'a> {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
let valA: usize = if self.value { 1 } else { 0 };
let valB: usize = if rhs.value { 1 } else { 0 };
let val = if valA ^ valB != 0 { true } else { false };
TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val }
}
}
This is basically pure guessing based on BitXor documentation . 这基本上是基于BitXor文档的纯粹猜测。 So what I try to do, in a very explicit manner, is to perform an xor operation on the two input variables and create a new TraceBit
as output with the inputs stored in it as reference. 因此,我尝试以非常明确的方式对两个输入变量执行异或运算,并使用存储在其中的输入作为参考来创建新的TraceBit
作为输出。
error[E0597]: `self` does not live long enough
--> libbittrace/src/lib.rs:37:30
|
37 | TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val }
| ^^^^ does not live long enough
38 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 31:1...
--> libbittrace/src/lib.rs:31:1
|
31 | / impl<'a> BitXor for TraceBit<'a> {
32 | | type Output = Self;
33 | | fn bitxor(self, rhs: Self) -> Self {
34 | | let valA: usize = if self.value { 1 } else { 0 };
... |
40 | |
41 | | }
| |_^
error[E0597]: `rhs` does not live long enough
--> libbittrace/src/lib.rs:37:53
|
37 | TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val }
| ^^^ does not live long enough
38 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 31:1...
--> libbittrace/src/lib.rs:31:1
|
31 | / impl<'a> BitXor for TraceBit<'a> {
32 | | type Output = Self;
33 | | fn bitxor(self, rhs: Self) -> Self {
34 | | let valA: usize = if self.value { 1 } else { 0 };
... |
40 | |
41 | | }
| |_^
error: aborting due to 2 previous errors
I've tried various workarounds/changes to the code but to no avail and in any way I rather like to understand the issue than guessing a correct solution.... 我已经尝试了各种变通办法/更改了代码,但无济于事,我以某种方式宁愿了解问题,也不愿猜测正确的解决方案。
Tree-like structures must use the Box
pointer type ( Option<Box<TraceBit>>
). 树状结构必须使用Box
指针类型( Option<Box<TraceBit>>
)。 In general, in structs you should prefer owned types. 通常,在结构中,您应该更喜欢拥有的类型。
Rust references aren't mere pointers. Rust引用不仅仅是指针。 They are borrows (compile-time read/write locks) of data that must exist as owned somewhere else. 它们是数据的借用(编译时读/写锁定),这些数据必须作为其他地方拥有。
So if you have an owned version of TraceBit
: 因此,如果您拥有TraceBit
的拥有版本:
pub struct TraceBit {
source_a: Option<Box<TraceBit>>,
}
then reference to it is of type: &'a TraceBit
, but references to a type don't change how the type looks internally, so the type of source_a
is still Box<TraceBit>
. 那么对该类型的引用为: &'a TraceBit
,但是对该类型的引用不会更改该类型在内部的外观,因此source_a
的类型仍为Box<TraceBit>
。 You can keep getting the &'a TraceBit
references recursively step by step: 您可以逐步获取&'a TraceBit
引用:
trace_bit = trace_bit.source_a.as_ref().unwrap();
but there's no construct in Rust where taking a reference to the root of a tree suddenly changes the whole tree into a tree of references, so the type you are creating can't exist, and that's why you can't get type annotations right. 但是Rust中没有构造,其中引用树的根会突然将整个树变成引用树,因此创建的类型不存在,这就是为什么不能正确获得类型注释的原因。
Maybe instead of passing references around, you should use a contained and cloneable name type. 也许不要使用传递的引用,而应该使用一个包含且可克隆的名称类型。
use std::rc::Rc;
#[derive(Debug)]
pub enum TraceOperation {
AND,
OR,
XOR,
NOT,
}
#[derive(Debug)]
pub enum BitName<T> {
Name(Rc<T>),
Combination(Rc<(TraceOperation, BitName<T>, BitName<T>)>),
}
impl<T> Clone for BitName<T> {
fn clone(&self) -> Self {
match self {
&BitName::Name(ref x) => BitName::Name(Rc::clone(x)),
&BitName::Combination(ref x) => BitName::Combination(Rc::clone(x)),
}
}
}
impl<T> From<T> for BitName<T> {
fn from(x:T) -> Self {
BitName::Name(Rc::new(x))
}
}
impl<T> BitName<T> {
pub fn combine(op : TraceOperation, a : &Self, b :&Self) -> Self {
BitName::Combination(Rc::new((op, (*a).clone(), (*b).clone())))
}
}
fn main() {
let x : BitName<String> = BitName::from(String::from("x"));
let y : BitName<String> = BitName::from(String::from("y"));
let xandy = BitName::combine(TraceOperation::AND, &x, &y);
println!("{:?}", xandy);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.