为什么不能在可变字符串引用上调用可变方法但适用于 TcpStream

Why can't a mutable method be called on a mutable String reference but works for TcpStream

当我试图理解一个可变变量之间的区别时,它恰好是一个引用,例如let mut x: &i32 与可变引用,例如let x: &mut i32,我发现这个差异我无法理解:

这有效,其中 by_ref 具有签名:fn by_ref(&mut self) -> &mut Self (docs)

fn example(mut t: &TcpStream) {
    t.by_ref();
}

但是以下 String,使用具有相似签名的方法,reserve

pub fn reserve(&mut self, additional: usize)`

但是这样不行,错误是:

"cannot borrow *str as mutable, as it is behind a & reference"

fn example(mut str: &String) {
    str.reserve(10);
}

有趣的是,这两个具有可变引用的示例有效,据我所知,这是使用可变方法的推荐方式:

fn example_stream(t: &mut TcpStream) {
    t.by_ref();
}

fn example_string(str: &mut String) {
    str.reserve(10);
}

那么 TcpStreamString 允许在一种情况下调用带有 &mut self 参数的方法而不是在另一种情况下调用的方法有什么不同?

您的 TcpStream 样本误导了您。

impl Read for TcpStream as you've linked to, but there is also impl Read for &TcpStream。您实际上使用的是后者,它不需要对 TcpStream 的可变访问,只需要对 TcpStreamreference 的可变访问,即 t.

这样做是因为 Read 特性使用可变方法来允许需要突变或独占访问权限的读者进行读取。然而 TcpStream 实际上不需要突变或独占访问来读取数据,因为它本质上只是服从系统调用。因此,TcpStream 可以更加灵活,并允许多个线程通过在其引用上实现 Read 从套接字 read/write。

另一方面,str.reserve() 调用没有这种奢侈,需要对 String 本身进行可变访问,因此 &String 是不够的。