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

Rust中简单类型何时及为何优先按值或引用传递?(附示例)

Rust中简单类型按值与引用传递的选择分析

先看示例结构体及Getter方法:

use chrono::{DateTime, Utc};
pub type Bytes = [u8; 16];
#[derive(Clone, Copy)]
pub struct Uuid(Bytes);


struct X {
    v_str: String,
    v_num: i32,
    v_bool: bool,
    v_uuid: Uuid,
    v_date: DateTime<Utc>,
}
impl X {
    pub fn v_str_ref(&self) -> &str {
        &self.v_str
    }
    pub fn v_str_val(&self) -> String {
        self.v_str.clone()
    }

    pub fn v_num_ref(&self) -> &i32 {
        &self.v_num
    }
    pub fn v_num_val(&self) -> i32 {
        self.v_num
    }

    pub fn v_bool_ref(&self) -> &bool {
        &self.v_bool
    }
    pub fn v_bool_val(&self) -> bool {
        self.v_bool
    }

    pub fn v_uuid_ref(&self) -> &Uuid {
        &self.v_uuid
    }
    pub fn v_uuid_val(&self) -> Uuid {
        self.v_uuid
    }

    pub fn v_date_ref(&self) -> &DateTime<Utc> {
        &self.v_date
    }
    pub fn v_date_val(&self) -> DateTime<Utc> {
        self.v_date
    }
}

下面针对不同类型逐一分析传递方式的选择:

1. 栈上小类型:i32、bool

这类类型的大小通常等于或小于指针大小(64位系统下指针为8字节,i32是4字节、bool是1字节),优先按值传递:

  • 性能上:直接传值的开销比传引用更低——引用需要额外存储指针、执行解引用操作,反而会增加指令开销。
  • 使用上:避免了借用检查器的约束,不需要处理生命周期、可变/不可变借用冲突等问题,代码更简洁。

2. 堆分配类型:String

这类类型的数据存储在堆上,结构体本身仅包含指针、长度、容量(3个机器字),优先传引用(&str):

  • 性能上:传递引用只需要复制8字节的指针,避免了克隆整个堆上字符串的昂贵开销。
  • 场景例外:当需要获得数据的所有权(比如要修改字符串、长期持有且不想受原结构体生命周期限制)时,才需要克隆并按值传递。

3. 实现Copy trait的自定义类型:Uuid

示例中的Uuid标注了#[derive(Clone, Copy)],意味着它是按位复制的类型,内部的[u8;16]是固定大小的栈数组,复制成本极低(仅16字节的内存拷贝),因此遵循和i32、bool一样的规则:优先按值传递。

  • 传引用反而画蛇添足:不仅不会提升性能,还会引入借用检查的额外约束,完全没必要。

4. 非Copy的中等大小类型:DateTime

DateTime<Utc>属于这类:它的数据完全存储在栈上(通常包含一个i64时间戳和Utc时区标记,总大小约16字节),但默认没有实现Copy trait,需要通过Clone复制。针对这类类型:

  • 只读场景:优先传引用&DateTime<Utc>,避免Clone带来的内存拷贝开销。
  • 需要所有权或简化代码:如果复制的开销(16字节拷贝)远低于处理借用规则的复杂度,也可以直接按值传递(示例中直接返回self.v_date是假设它可Copy,实际若需Clone则调用clone())。
  • 和String的区别:DateTime没有堆分配,复制开销远小于克隆String,所以传值的场景比String更多,不需要像String那样严格优先传引用。

针对你的疑问总结

  • Uuid因为是Copy类型,和数值、布尔类型规则一致,优先按值传递。
  • DateTime<Utc>和String规则不同:它是栈上的中等大小类型,复制开销低,传值场景更多;而String是堆分配类型,必须优先传引用以避免昂贵的克隆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 03:44:51