Rust代码中Box::new的作用及为何用其封装BufReader
Box::new的作用 先看你的代码:
let mut buf: Box<dyn BufRead> = Box::new(BufReader::new(fs::File::open("file.txt")?));
这里用Box::new封装BufReader的核心原因和Rust的类型系统特性直接相关,分三点说明:
解决动态大小类型(DST)的存储限制
dyn BufRead是trait对象,属于动态大小类型——编译时Rust无法确定它对应具体实现类型的内存占用,因此不能直接将trait对象声明为栈上变量(栈上变量必须是编译期大小确定的类型)。Box<T>是堆分配智能指针,它本身的大小固定(就是一个指向堆内存的指针),把BufReader放到堆上并用Box包裹后,既能满足编译期对变量大小的要求,又能通过Box<dyn BufRead>实现对trait接口的调用。实现动态多态的抽象需求
如果直接用BufReader::new的返回值,变量类型会是具体的BufReader<File>。但这里显式指定Box<dyn BufRead>,是为了让这个变量兼容任何实现了BufReadtrait的类型——比如后续你想把数据源换成Cursor<Vec<u8>>(同样实现了BufRead),只需要替换Box::new里的内容,变量类型不用修改,就能复用所有基于BufRead接口的逻辑,这就是Rust中动态多态的实现方式。不封装的后果
要是尝试写let mut buf: dyn BufRead = BufReader::new(...),编译器会直接报错,因为trait对象作为栈变量时大小不确定。而如果不指定trait对象类型,直接let mut buf = BufReader::new(...),虽然能正常运行,但变量会绑定到具体的BufReader<File>类型,失去了抽象能力,后续无法无缝切换其他BufRead实现。
内容的提问来源于stack exchange,提问作者LouisWong

