Reference 为什么我可以只传递一个不可变的引用到BufReader,而不是一个可变的引用?

Reference 为什么我可以只传递一个不可变的引用到BufReader,而不是一个可变的引用?,reference,rust,immutability,borrowing,Reference,Rust,Immutability,Borrowing,我正在编写一个简单的基于TCP的echo服务器。当我试图使用BufReader和BufWriter读取和写入TcpStream时,我发现通过值将TcpStream传递给BufReader::new()会移动其所有权,因此我无法将其传递给BufWriter。然后,我在中找到了解决问题的答案: fn handle_client(stream: TcpStream) { let mut reader = BufReader::new(&stream); let mut writ

我正在编写一个简单的基于TCP的echo服务器。当我试图使用
BufReader
BufWriter
读取和写入
TcpStream
时,我发现通过值将
TcpStream
传递给
BufReader::new()
会移动其所有权,因此我无法将其传递给
BufWriter
。然后,我在中找到了解决问题的答案:

fn handle_client(stream: TcpStream) {
    let mut reader = BufReader::new(&stream);
    let mut writer = BufWriter::new(&stream);

    // Receive a message
    let mut message = String::new();
    reader.read_line(&mut message).unwrap();

    // ingored
}
这很简单,而且有效。然而,我不太明白为什么这段代码可以工作。为什么我可以只传递一个不可变的引用到
BufReader::new()
,而不是一个可变的引用

整个程序都可以找到

更多详细信息

在上面的代码中,我使用了
reader.read\u line(&mut message)
。因此,我在Rust标准库中打开了
BufRead
的源代码,看到了以下内容:

fn read_line(&mut self, buf: &mut String) -> Result<usize> {
    // ignored
    append_to_string(buf, |b| read_until(self, b'\n', b))
}
在本部分中,有两个地方使用了
BufReader
r.fill\u buf()
r.consume(used)
。我想
r.fill\u buf()
是我想看到的。因此,我访问了Rust标准库中的
BufReader
代码,发现:

fn fill_buf(&mut self) -> io::Result<&[u8]> {
    // ignored
    if self.pos == self.cap {
        self.cap = try!(self.inner.read(&mut self.buf));
        self.pos = 0;
    }
    Ok(&self.buf[self.pos..self.cap])
}
从上面的代码中,我们可以知道
internal
是一种实现
Read
的类型。在我的例子中,
内部
可能是一个
&TcpStream

我知道
Read.Read()
的签名是:

fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn读取(&mut self,buf:&mut[u8])->结果

这里需要一个可变的引用,但我只借给它一个不可变的引用。当程序到达
fill\u buf()
中的
self.internal.read()
时,这应该是一个问题吗

快速应答:我们将
&TcpStream
传递为
R:Read
,而不是
TcpStream
。因此,
Read::Read
中的
self
&mut&TcpStream
,而不是
&mut-TcpStream
<代码>读取是为
&TcpStream
实现的,如您所见

看看这个工作代码:

let stream = TcpStream::connect("...").unwrap();
let mut buf = [0; 100];
Read::read(&mut (&stream), &mut buf);
请注意,
stream
甚至没有绑定为
mut
,因为我们不可变地使用它,只是有一个对不可变的引用


下一步,您可以询问为什么可以为
和TcpStream
实现
读取
,因为在读取操作过程中需要对某些内容进行变异


这就是我最初认为TcpStream的工作方式与文件不同的地方。但是在读了卢卡斯·卡尔伯托德的答案后,我突然意识到背后的想法是一样的。谢谢你的链接。我完全没有想到
self
&mut&TcpStream
!!但是,到底是什么呢?我是说。。。什么是引用的可变引用?如果我调用
self.something
,当
self
TcpStream
&TcpStream
时,会有同样的效果吗?@玉山林会有同样的效果->在这种情况下是的。dot语法做了一些事情,比如deref强制。此主题太大,无法进行后续评论^ ^Ok。谢谢你的回复。您关于为什么
Read
可以实现为一个不可变参考的补充是有用的!!你的回答对我帮助很大。
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
let stream = TcpStream::connect("...").unwrap();
let mut buf = [0; 100];
Read::read(&mut (&stream), &mut buf);