gpt4 book ai didi

rust - 为什么这会变成堆栈溢出?

转载 作者:行者123 更新时间:2023-12-01 13:10:52 26 4
gpt4 key购买 nike

因堆栈溢出而失败的简单测试用例:

// trait to say FnMut has a clone_box method
pub trait ClonableFnMut<A>: FnMut(A) {
fn clone_box(&self) -> Box<dyn ClonableFnMut<A> + Send + 'static>;
}

// overridden .clone() for Box<ClonableFnMut> that calls .clone_box on f
impl<A: 'static> Clone for Box<dyn ClonableFnMut<A> + Send + 'static> {
fn clone(&self) -> Self {
self.clone_box()
}
}

// .clone_box() on FnMut clones itself and wraps itself in a new Box
impl<A, F: FnMut(A) + Clone + Send + 'static> ClonableFnMut<A> for F {
fn clone_box(&self) -> Box<dyn ClonableFnMut<A> + Send + 'static> {
Box::new(self.clone())
}
}

fn main() {
let mut f: Box<dyn ClonableFnMut<u8> + Send + 'static> = Box::new(|_x|{});

println!("{:?}", f(3));
println!("{:?}", f.clone()(4));
}

理论上:

  1. 调用.clone()Box<ClonableFnMut> .
  2. 自定义实现调用 .clone_box()在内FnMut .
  3. 内部FnMut现在可以调用.clone()自身,因为它被标记为克隆。
  4. .clone_box()返回这个克隆的 FnMut (自己)在一个新的盒子里

但实际上:

  1. 调用 .clone()手动 Box<ClonableFnMut> .
  2. 调用 .clone_box()在内Box<FnMut> .
  3. 调用 self.clone()这似乎意味着 self = box .
  4. 自定义 Box<FnMut> clone()再次调用,从第 1 步开始。

第 4 步发生的真正原因是什么?

最佳答案

实际发生的事情略有不同:

  1. 有人调用 cloneBox ...
  2. ...调用clone_box相同Box ...
  3. ...调用clone相同Box 再次关闭循环。

发生这种情况是因为您实现了 Clone只调用 self.clone_box() ,但是 clone_boxClonableFnMut 的一种方法特征。此特性特别在 Box<dyn ClonableFnMut<A> + Send + 'static> 上实现由于一揽子实现,其要求 F: FnMut(A) + Clone + Send + 'static对 Box 本身感到满意。

为避免这种情况,您需要强制执行 Clone调用 clone_box 的实现Box 内容的方法, 不适用于 Box本身。有两种风格略有不同的明显方式:

  1. Replace self.clone_box()self.deref().clone_box()并添加所需的导入 use std::ops::Deref;某处。

  2. 或者,replace self.clone_box()(**self).clone_box() ,不需要额外导入,但看起来有点神秘。请注意克隆的参数,&self , 基本上是 self: &Self 的语法糖, 所以第一个 *&Box<F> 中取消引用它至 Box<F>第二个再次将其取消引用为 F .打电话clone_box然后将其自动引用到 &F因为它需要 &self也是。

关于rust - 为什么这会变成堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60120406/

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