You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何实现「引用现有值或新建值后引用」的惯用写法

Rust 中实现「复用现有引用/创建新值后取引用」的优雅方案

问题场景

Rust 开发中常遇到这类逻辑需求:

  • 满足特定条件时,直接使用已经存在的引用
  • 不满足条件时,创建一个新的所有值(owned value),再使用指向这个新值的引用

最直观的写法会触发生命周期编译错误:

let variable = &some_ref;

let variable = if something {
  let new_variable = create_something();
  &new_variable // 编译报错:`new_variable` 存活时间不足,if 分支结束就会被 drop,返回的是悬空引用
} else {
  variable
};

// 后续使用 variable

不少开发者为了绕开这个错误,会选择把后续使用变量的逻辑完整复制到两个分支中,比如实际开发中的图片处理场景:

let source = &source;

if is_position_negative(x, y) {
  let source = crop(source, x, y);
  overlay_with_u32(destination, &source, x, y);
} else {
  overlay_with_u32(destination, source, x, y);
};

这种写法在后续逻辑复杂时会产生大量重复代码,维护成本很高。

符合 Rust 惯用法的解决方案

核心原则很简单:让新创建的 owned 值的生命周期覆盖引用的整个使用范围,不要让值在 if 分支内部就被销毁。常用的实现有两种,都不需要重复写业务逻辑。

方案1:局部作用域提前声明占位变量(无额外依赖,最轻量)

在 if 逻辑的外层提前声明存储新 owned 值的变量,分支内仅做赋值操作,最后统一获取引用:

let original_ref = &some_ref;
// 提前声明占位变量,生命周期覆盖后续所有引用使用的范围
let new_owned_val;

let variable = if something {
  new_owned_val = create_something();
  &new_owned_val
} else {
  original_ref
};

// 后续直接使用 variable 即可,无生命周期问题

对应之前的图片处理场景,改造后代码如下:

let original_source = &source;
let cropped_source;

let source_ref = if is_position_negative(x, y) {
  cropped_source = crop(original_source, x, y);
  &cropped_source
} else {
  original_source
};

overlay_with_u32(destination, source_ref, x, y);

这种写法没有任何额外抽象,编译器能完全优化,运行时没有额外开销,适合局部临时使用的场景。

方案2:使用标准库 Cow 类型(语义更清晰,适合跨 scope 传递)

如果逻辑需要跨函数传递、或者后续存在修改值的需求,可以使用标准库提供的 Cow(Clone-on-Write,写时克隆)枚举,它天生就是为「要么借用引用、要么持有所有权」的场景设计的:

  • Cow::Borrowed(&T) 存储一个借用的引用
  • Cow::Owned(T) 持有一个 owned 值
  • Cow 自动实现了 Deref<Target = T>,可以直接当作 &T 使用,不需要手动解引用

示例代码:

use std::borrow::Cow;

// 声明时不需要额外占位变量,直接在分支中返回对应的 Cow 枚举即可
let variable: Cow<'_, SomeType> = if something {
  Cow::Owned(create_something())
} else {
  Cow::Borrowed(original_ref)
};

// 直接使用 variable,会自动解引用为 &SomeType
// 比如调用 variable.some_method() 和用普通引用的效果完全一致

对应图片处理场景的写法:

use std::borrow::Cow;

let source_ref: Cow<'_, [u32]> = if is_position_negative(x, y) {
  Cow::Owned(crop(source, x, y))
} else {
  Cow::Borrowed(source)
};

overlay_with_u32(destination, &source_ref, x, y);

写法选择参考

  • 仅在单个局部作用域使用时,优先选方案1,代码最轻量无额外抽象
  • 需要跨函数传值、后续可能涉及修改值的场景,选方案2,语义更明确

注:最开始的直观写法报错是 Rust 内存安全机制的正常校验——分支内声明的变量作用域仅在分支内部,分支结束值就会被自动释放,此时返回引用必然指向无效内存,编译器会直接拦截这类风险。

内容的提问来源于stack exchange,提问作者antonmelnyk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 21:54:28