【问题标题】:Is there a way to distinguish between different `Rc`s of the same value?有没有办法区分相同值的不同`Rc`?
【发布时间】:2016-06-08 15:18:10
【问题描述】:

这是一个例子:

use std::rc::Rc;

#[derive(PartialEq, Eq)]
struct MyId;

pub fn main() {
    let rc_a_0 = Rc::new(MyId);
    let rc_a_1 = rc_a_0.clone();
    let rc_b_0 = Rc::new(MyId);
    let rc_b_1 = rc_b_0.clone();

    println!("rc_a_0 == rc_a_1: {:?}", rc_a_0 == rc_a_1);
    println!("rc_a_0 == rc_b_0: {:?}", rc_a_0 == rc_b_0);
}

上面的println!s 都打印true。有没有办法区分 rc_a_*rc_b_* 指针?

【问题讨论】:

    标签: rust identity smart-pointers reference-counting


    【解决方案1】:

    2017 稳定更新(2020 年)。

    在 Rust 1.17 及更高版本中,您可以使用 Rc::ptr_eq。它与ptr::eq 的作用相同,无需将Rc 转换为引用或指针。

    引用相等

    正如其他答案提到的Rc::ptr_eq(和ptr::eq)检查引用是否相等,即两个引用是否“指向”相同的地址。

    let five = Rc::new(5);
    let same_five = Rc::clone(&five);
    let other_five = Rc::new(5);
    
    // five and same_five reference the same value in memory
    assert!(Rc::ptr_eq(&five, &same_five));
    
    // five and other_five does not reference the same value in memory
    assert!(!Rc::ptr_eq(&five, &other_five));
    

    示例来自 Rust Rc::ptr_eq 文档。

    价值平等

    Rc 实现了PartialEq,所以像往常一样简单地使用== 来执行值相等,即值是否相等,与它们是否引用内存中的相同地址无关。

    use std::rc::Rc;
    
    let five = Rc::new(5);
    let other_five = Rc::new(5);
    
    let ten = Rc::new(10);
    
    assert!(five == other_five);
    
    assert!(ten != five);
    assert!(ten != other_five);
    

    【讨论】:

      【解决方案2】:

      您可以将&*rc 转换为*const T 以获取指向基础数据的指针并比较这些指针的值:

      use std::rc::Rc;
      
      #[derive(PartialEq, Eq)]
      struct MyId;
      
      pub fn main() {
          let rc_a_0 = Rc::new(MyId);
          let rc_a_1 = rc_a_0.clone();
          let rc_b_0 = Rc::new(MyId);
          let rc_b_1 = rc_b_0.clone();
      
          println!(
              "rc_a_0 == rc_a_1: {:?}",
              &*rc_a_0 as *const MyId == &*rc_a_1 as *const MyId
          );
          println!(
              "rc_a_0 == rc_b_0: {:?}",
              &*rc_a_0 as *const MyId == &*rc_b_0 as *const MyId
          );
      }
      

      打印

      rc_a_0 == rc_a_1: true
      rc_a_0 == rc_b_0: false
      

      【讨论】:

        【解决方案3】:

        与 Dogbert 的答案相同,但可能更简洁:

        use std::ptr;
        
        println!(
            "rc_a_0 == rc_a_1: {:?}",
            ptr::eq(rc_a_0.as_ref(), rc_a_1.as_ref())
        );
        println!(
            "rc_a_0 == rc_b_0: {:?}",
            ptr::eq(rc_a_0.as_ref(), rc_b_0.as_ref())
        );
        
        rc_a_0 == rc_a_1: true
        rc_a_0 == rc_b_0: false
        

        简而言之,您需要引用相等,而不是值相等。原始指针的值是内存地址,因此比较原始指针的值相当于引用相等。

        另见:

        【讨论】:

        • 为了比较指针,最好总是先转换为*const MyType,或者至少在ptr::eq::<MyType>(...) 中指定类型。否则,您可能会比较错误的类型(例如 &&MyType 而不是 &MyType,或 Derefed 值)。
        猜你喜欢
        • 2012-03-13
        • 2020-12-20
        • 1970-01-01
        • 2020-09-18
        • 1970-01-01
        • 2019-06-15
        • 2023-03-18
        • 1970-01-01
        • 2012-10-11
        相关资源
        最近更新 更多