gpt4 book ai didi

rust - 如何使用相同的可变借用调用 serde_json::to_writer 两次?

转载 作者:行者123 更新时间:2023-11-29 07:55:31 26 4
gpt4 key购买 nike

我正在尝试编写一个调用 serde_json::to_writer 的函数两次写两件事,但我不知道怎么写。

这是一次尝试 ( playground link ):

extern crate serde_json;

fn main() {
let mut out = std::fs::File::create("out.txt").unwrap();
write_stuff(&mut out);
}

fn write_stuff<W: ?Sized>(out: &mut W) -> Result<(), std::io::Error>
where
W: std::io::Write,
{
serde_json::to_writer(out, &1).unwrap(); // `out`: value moved here
serde_json::to_writer(out, &2).unwrap(); // `out`: value used here after move
Ok(())
}

编辑:想出了一个编译的方法,但是有没有更简单的方法(playground link):

extern crate serde_json;

fn main() {
let mut out = std::fs::File::create("out.txt").unwrap();
write_stuff(&mut out);
}

fn write_stuff<W: ?Sized>(out: &mut W)
where
W: std::io::Write,
{
write_wrapper(out);
write_wrapper(out);
}

fn write_wrapper<W: ?Sized>(out: &mut W)
where
W: std::io::Write,
{
serde_json::to_writer(out, &1).unwrap();
}

最佳答案

这种行为的原因有些微妙。当将共享引用作为参数传递给函数时,Rust 将简单地复制引用。 &T 类型对于所有 T 都是Copy,因为我们可以同时拥有任意数量的共享引用。

另一方面,可变引用不是Copy,因为在任何给定时间只能有一个。根据非 Copy 类型的常用 Rust 语义,这意味着可变引用在作为参数传递时应该移动。那么为什么这段代码有效呢?

fn foo(_: &mut i32) {}

fn main() {
let mut i = 42;
let r = &mut i;
foo(r);
foo(r);
}

原因是编译器在分配给显式声明为可变引用的变量时创建一个隐式重借,因此函数调用被转换为 foo(&mut *r )。这将创建一个仅在函数调用期间持续的新借用,一旦重新借用的生命周期结束,原始引用 r 将再次可用。

但是,隐式重借仅针对使用可变引用类型显式声明的变量生成。如果我们将上面的 foo() 的定义更改为

fn foo<T>(_: T) {}

代码将停止编译。现在 foo() 的参数不再声明为可变引用,因此编译器不会引入隐式重借,并将 r 的所有权转移到函数中而是第一次调用,导致第二次函数调用出错。

同样的事情发生在你的代码中。函数 to_writer() 声明为

pub fn to_writer<W, T: ?Sized>(writer: W, value: &T) -> Result<()>
where
W: io::Write,
T: Serialize,

由于参数 writer 没有被声明为可变引用,你需要创建一个显式的 reborrow 来避免移动:

serde_json::to_writer(&mut *out, &1)?;

您在问题中给出的替代解决方案同样有效——write_wrapper() 函数接收一个显式声明的可变引用作为参数,因此对该函数的调用会触发隐式重借。

关于rust - 如何使用相同的可变借用调用 serde_json::to_writer 两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58316486/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com