为何为自定义集合实现IntoIterator时针对&T而非T类型?
IntoIterator trait的疑问 我正在学习如何为自定义集合实现IntoIterator trait,比如HashMap的实现。我有一个疑问:为何要针对&T类型实现该trait,而非直接针对T类型?用户难道不会想要直接在集合上调用into_iter方法吗?
核心原因:所有权与使用场景的区分
Rust里实现IntoIterator的不同版本,本质是为了适配三种完全不同的迭代需求,而针对&T实现只是其中一种:
针对
T本身实现IntoIterator:
这种实现会把集合的所有权转移给迭代器,迭代完成后原集合就不能再使用了。用户完全可以直接调用into_iter,比如当你不再需要原集合,想一次性消费它的时候——比如把集合里的元素转移到另一个容器里。针对
&T实现IntoIterator:
这是为了支持只读借用迭代,迭代过程中原集合依然可用。日常开发里这种场景其实最多:你只是想遍历集合里的元素做读取操作,不想动原集合的所有权。而且Rust的语法糖会自动帮你处理——当你写for item in &my_collection的时候,其实就是在调用针对&T实现的IntoIterator。针对
&mut T实现IntoIterator:
对应可变借用迭代,允许你遍历并修改集合里的元素,同时保留原集合的所有权。
为什么你会觉得“优先针对&T实现”?
你看到的HashMap实现里包含&T的版本,是因为它要覆盖最常用的场景。实际上标准库的HashMap同时实现了这三种版本:
impl<K, V> IntoIterator for HashMap<K, V>:转移所有权,迭代器产出(K, V)impl<K, V> IntoIterator for &HashMap<K, V>:只读借用,迭代器产出(&K, &V)impl<K, V> IntoIterator for &mut HashMap<K, V>:可变借用,迭代器产出(&K, &mut V)
用户当然可以直接在集合上调用into_iter——当你写for item in my_collection的时候,就是在调用针对T的实现,这会把集合的所有权移走。只是很多时候我们不需要这么做,所以&T的版本反而更常用,也更容易被注意到。
内容的提问来源于stack exchange,提问作者Mandroid

