Rust是否会可靠优化掉即将被立即丢弃的clone()调用?
Rust中
std::mem::replace配合克隆的优化可靠性疑问 99%的场景下这都无关紧要,但对于像我这样有点焦虑的开发者来说,还是想彻底弄明白:
假设调用一个复杂库函数,它返回一个可变引用,而我需要返回该引用指向的值。刚好这个引用指向的类型实现了Clone trait,为了避免大量重构,我写出了如下代码:
fn common_behavior(specs: Specs) -> ClonableThing { let mut intermediate_thing = IntermediateThing::new(specs); let clonable_thing: &mut ClonableThing = intermediate_thing.create_mut_ref_to_thing(); // 这里的clone操作能被可靠地优化掉吗? std::mem::replace(clonable_thing, clonable_thing.clone()) }
显然,clonable_thing.clone()生成的替换值会在intermediate_thing及其他变量离开作用域时被立即丢弃,但我们能不能指望克隆操作本身不会被执行?前提是intermediate_thing是一个相当复杂的结构体,克隆仅由#[derive(Clone)]自动生成。
结论:不能依赖这个优化被可靠执行
原因很直接:
- Rust依赖LLVM做优化,但LLVM的死代码消除(DCE)只会移除完全无副作用且未被使用的代码。如果
ClonableThing包含Rc/Arc这类带引用计数的类型,克隆会修改计数,属于有副作用操作,编译器绝对不会优化掉;哪怕是纯数据结构,只要编译器无法明确判定克隆操作没有副作用,就不会贸然移除。 - 当
intermediate_thing结构复杂时,编译器可能无法追踪到"克隆出的值完全没被使用"这一逻辑,导致优化失效。
更可靠的替代方案
- 修改库代码(如果可行):给
IntermediateThing添加一个转移所有权的方法,比如take_thing(&mut self) -> ClonableThing,直接拿到值的所有权,完全不需要克隆。 - 用轻量默认值替换(如果类型实现
Default):
fn common_behavior(specs: Specs) -> ClonableThing { let mut intermediate_thing = IntermediateThing::new(specs); let clonable_thing: &mut ClonableThing = intermediate_thing.create_mut_ref_to_thing(); let result = clonable_thing.clone(); // 用Default生成的轻量值替换原位置,避免克隆替换值 std::mem::replace(clonable_thing, ClonableThing::default()); result }
这种写法虽然还是要克隆目标值,但替换值的开销更小,逻辑也更清晰,不会依赖不确定的优化。
3. 如果类型实现Copy:直接解引用返回即可(*clonable_thing),但既然用到Clone,大概率没实现Copy。
内容的提问来源于stack exchange,提问作者Dunedubby
相关产品推荐
相关产品推荐

