首页 > 解决方案 > 为什么 Serde 默认不支持 Rc 和 Arc 类型?

问题描述

请解释一下 Serderc功能

选择 impls forRc<T>Arc<T>. 序列化和反序列化这些类型不会保留身份,并且可能导致相同数据的多个副本。在启用此功能之前,请确保这是您想要的。

每次在数据结构中引用指针时,序列化包含引用计数指针的数据结构将序列化指针内部值的副本。序列化不会尝试对这些重复数据进行重复数据删除。

反序列化包含引用计数指针的数据结构不会尝试对相同数据的重复引用进行删除。每个反序列化的指针都会以强计数 1 结束。

为什么这个功能标志存在,为什么它不是默认行为?这是什么意思

序列化和反序列化这些类型不会保留身份,并且可能导致相同数据的多个副本

我知道它与Serde issue 194有关。该问题的最后一条消息

如果您想确保不会意外地得到包含 rc 的派生 impl,请打开一个 clippy 问题。

是否存在功能标志来捕获Rc结构的意外用法?

标签: rustreference-countingserde

解决方案


Serde issue 194中所述,反序列化到Rcor的实现的缺点Arc是:

  • 可能会增加内存使用量
  • 依赖于地址中断比较的相等比较
  • 内部可变性未反映在副本中

这在功能标志文档中得到了回应:

序列化不会尝试对这些重复数据进行重复数据删除。

反序列化包含引用计数指针的数据结构不会尝试对相同数据的重复引用进行删除。

Rcor的通常点Arc共享数据。Rc当反序列化为包含or的结构时,不会发生这种共享Arc。在此示例中,Rc<str>创建了 5 个完全不同的 s,彼此没有任何关系,即使它们都具有相同的内容:

use std::{rc::Rc, ptr};

fn main() {
    let json = r#"[
        "alpha",
        "alpha",
        "alpha",
        "alpha",
        "alpha"
    ]"#;

    let strings = serde_json::from_str::<Vec<Rc<str>>>(json).unwrap();
    
    dbg!(ptr::eq(strings[0].as_ref(), strings[1].as_ref()));
}
[src/main.rs:14] ptr::eq(strings[0].as_ref(), strings[1].as_ref()) = false

当您拥有Rc<RefCell<_>>具有内部可变性的类型或其他类型时,这尤其糟糕,因为您可能期望修改其中一个项目会修改所有项目。

也可以看看:


推荐阅读