簡體   English   中英

結構參考的Rust壽命

[英]Rust lifetimes for struct references

我剛開始使用Rust,但是不能完全掌握一生,因此我可以自己解決以下問題:

該測試項目是關於模擬一個位以允許通過各種按位操作對其進行跟蹤,例如, let newbit = oldbit1 ^ oldbit2並查看newbit之后,我可以分辨出它來自於以oldbit1oldbit2作為操作數的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,
}

可以編譯,但是我不完全理解為什么需要這種壽命參數。 我假設編譯器不能期望成員source_asource_b生存,只要結構本身不成立即可,因此需要顯式的生存期。

  • 這個假設正確嗎?

此外,我不完全理解為什么我必須為引用類型重新指定生命周期參數,即為什么我必須編寫source_a: Option<&'a TraceBit<'a>>而不是source_a: Option<&'a TraceBit>

  • 第二生命是用來做什么的? 我如何大聲讀出那條線? 我有:“ source_aOption類型的變量,可能對TraceBit實例具有Some引用(至少在結構本身和成員source_b

我的最后一個問題是我無法使用重載運算符來使其工作:

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 }
        }
}

這基本上是基於BitXor文檔的純粹猜測。 因此,我嘗試以非常明確的方式對兩個輸入變量執行異或運算,並使用存儲在其中的輸入作為參考來創建新的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
  • 似乎沒有什么比“異或”操作本身壽命更長,但是我該如何解決呢?

我已經嘗試了各種變通辦法/更改了代碼,但無濟於事,我以某種方式寧願了解問題,也不願猜測正確的解決方案。

樹狀結構必須使用Box指針類型( Option<Box<TraceBit>> )。 通常,在結構中,您應該更喜歡擁有的類型。

Rust引用不僅僅是指針。 它們是數據的借用(編譯時讀/寫鎖定),這些數據必須作為其他地方擁有。

因此,如果您擁有TraceBit的擁有版本:

pub struct TraceBit {
    source_a: Option<Box<TraceBit>>,
}

那么對該類型的引用為: &'a TraceBit ,但是對該類型的引用不會更改該類型在內部的外觀,因此source_a的類型仍為Box<TraceBit> 您可以逐步獲取&'a TraceBit引用:

trace_bit = trace_bit.source_a.as_ref().unwrap();

但是Rust中沒有構造,其中引用樹的根會突然將整個樹變成引用樹,因此創建的類型不存在,這就是為什么不能正確獲得類型注釋的原因。

也許不要使用傳遞的引用,而應該使用一個包含且可克隆的名稱類型。

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.

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