Why does BufWriter wrap the inner Write in an Option?
在标准库中,BufWriter声明如下:
1 2 3 4 5 6 7 8
| pub struct BufWriter<W: Write> {
inner: Option<W>,
buf: Vec<u8>,
// #30888: If the inner writer panics in a call to write, we don't want to
// write the buffered data a second time in BufWriter's destructor. This
// flag tells the Drop impl if it should skip the flush.
panicked: bool,
} |
正如文档所告诉我们的那样,panicked的存在是为了防止展开时发生两次重复写入,我理解其背后的原因。将内部编写器包裹在Option中是否有类似的原因?我在代码中找到的唯一真正清除了Option的部分是在into_inner中,但是我看不出为什么用裸值也不可能做到这一点,因为self由值所取。 >
原因很简单:BufWriter实现Drop,并且您不能从实现Drop的类型中移出字段。在BufWriter::into_inner返回之前,将调用BufWriter::drop,因为BufWriter被移到了函数的self参数中,然后超出了范围–这是标准的RAII。
如果您能够移出某个字段,那么析构函数会发生什么?要么根本不会调用它,这会令人惊讶,或者将使用包含无效值的某些字段来调用它,这可能会破坏内存安全性。
- 我没想到。那么,您还可以使用该选件来防范panic吗? IE。代替self.panicked = true,暂时take内部编写器,然后将其还给。
-
@HeroicKatora我认为是这样,但它可能会稍微贵一些,因为它将涉及制作两个(浅)副本的W(我们不知道其大小)。另一方面,panicked字段的长度为一个字节,因此这是已知的,较小的固定成本。
-
相关:RFC 2061:Destruct丢弃结构在几天前已关闭为postponed。
-
PR#36336也相关。