Reference 为什么我可以只传递一个不可变的引用到BufReader,而不是一个可变的引用?
我正在编写一个简单的基于TCP的echo服务器。当我试图使用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
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);