Rust中用Copy/Clone修复“use of moved value”错误开销很大吗?
问题分析
原始报错原因
原始代码的minus方法采用值传递接收scalar: T,执行self.x - scalar时,scalar的所有权会被转移到sub方法的入参中,后续y、z字段再访问scalar就会触发use of moved value: 'scalar'的所有权错误,完全符合Rust的所有权规则。
方案1的优劣
给T添加Clone约束确实可以解决所有权问题,但三次clone()调用对于大尺寸的非基础类型T来说,确实会产生额外的拷贝开销;如果改为Copy约束,虽然对于数值类小类型是零开销,但不支持非Copy的自定义类型,适用范围受限。
方案2报错原因
你尝试用引用传递scalar的思路是对的,但是你当前的泛型约束T: Sub<Output=T>仅声明了T - T类型的减法实现,而你代码里实际执行的是&T - &T类型的运算。Rust的运算符trait是和操作数类型严格绑定的,两种操作数组合的trait实现相互独立,编译器找不到&T类型的减法实现,就会抛出cannot subtract '&T' from '&T'的错误。
最优解决方案
不需要对scalar做任何Clone或Copy,只需要调整泛型约束,声明支持引用类型的减法即可:
use std::ops::Sub; struct Point<T> { x: T, y: T, z: T, } impl<T> Point<T> where // 高阶生命周期约束:任意生命周期的&T都支持和&T做减法,返回T for<'a> &'a T: Sub<&'a T, Output = T> { fn minus(self, scalar: &T) -> Self { Point { x: &self.x - scalar, y: &self.y - scalar, z: &self.z - scalar, } } }
方案说明
- 全程使用引用完成计算,没有任何拷贝开销,性能最优
- 标准库所有数值类型(i32、f64、u64等)都默认实现了该引用减法约束,常用场景可以直接使用
- 自定义类型只要实现了
&T - &T的Subtrait,就可以无缝适配该实现,适用范围更广
内容的提问来源于stack exchange,提问作者user438454534
相关产品推荐
相关产品推荐

