В документации Rust для std::io::Read::read() я наткнулся на такой пример:
fn main() -> io::Result<()> {
let mut f = File::open("foo.txt")?;
let mut buffer = [0; 10];
// read up to 10 bytes
let n = f.read(&mut buffer[..])?;
// Is there any difference between the previous line and the next one?
// let n = f.read(&mut buffer)?;
println!("The bytes: {:?}", &buffer[..n]);
Ok(())
}
Вы можете видеть, что let n = f.read(&mut buffer[..])?;
, buffer[ .. ]
содержит все значения от начала до конца, а затем у нас есть изменяемая ссылка на них.
Будет ли какая-то разница, если я вместо этого напишу let n = f.read(&mut buffer)?;
?
Я попробовал, и мне кажется то же самое, но мне стало интересно, почему авторы использовали &mut buffer[..]
, я что-то упускаю?
В примере это массив, поэтому технически это не разыменование, но это приведение.
Принудить &mut [u8; 10]
к &mut [u8]
@TimsibAdnap Я бы рекомендовал .as_mut_slice() вместо &mut [..]
. Но я согласен с ОП, простой &mut
тоже подойдет и, по моему мнению, лучше.
@drewtato Если вы хотите быть педантичным, это приведение к неразмерному значению.
Типы разные:
buffer
[u8; 10]
&mut buffer
&mut [u8; 10]
&mut buffer[..]
&mut [u8]
buffer.as_mut_slice()
&mut [u8]
Так почему же функция, которой нужен аргумент &mut [u8]
, может принимать &mut buffer
?
Волшебство здесь заключается в автоматическом приведении типов , которое гласит, что &mut [u8; 10]
можно автоматически привести к &mut [u8]
.
Функционально разницы нет. Это похоже на разницу между явным и неявным приведением типов. &mut [..]
явно преобразуется в срез, и приведение не происходит, &mut
не преобразуется явно, и происходит неявное приведение. Результирующий машинный код будет идентичен.
Дополнительную информацию о разнице между [u8; 10]
и [u8]
читайте В чем разница между срезом и массивом?.
Так что писать f.read(&mut buffer)
вполне нормально, и, на мой взгляд, предпочтительнее, чем f.read(&mut buffer[..])
. Это просто легче читать.
Обновлено: @ChayimFriedman отметил, что принуждение не всегда происходит автоматически, и это правильно. Принуждение может иметь место только на сайтах принуждения . Соответствующий сайт приведения для этого примера использует переменную в качестве «аргумента для вызова функции». Если у вас есть ситуация, когда сайт приведения отсутствует, тогда явное преобразование действительно может потребоваться.
Обратите внимание, что иногда (не в этом случае) принуждение не срабатывает, поэтому необходима явность.
&mut buffer
означает то же самое, что и&mut buffer[..]
только в тех местах, где разрешено приведение к разыменованию, при условии, чтоbuffer
являетсяVec