Rust中的&str与String用法举例

举报
福州司马懿 发表于 2025/12/03 15:41:05 2025/12/03
【摘要】 在 Rust 中,&str 和 String 是两种不同的字符串类型,分别用于不同的场景。以下是它们的区别和适用场景: 1. 核心区别特性&str(字符串切片)String(可增长字符串)所有权借用(不拥有数据,只是引用)拥有数据(独占所有权)内存分配通常指向静态数据或已分配的内存(如 String 的切片)在堆上动态分配内存可变性不可变(除非通过 &mut str,但极少用)可变(支持修改...

在 Rust 中,&strString 是两种不同的字符串类型,分别用于不同的场景。以下是它们的区别和适用场景:


1. 核心区别

特性 &str(字符串切片) String(可增长字符串)
所有权 借用(不拥有数据,只是引用) 拥有数据(独占所有权)
内存分配 通常指向静态数据或已分配的内存(如 String 的切片) 在堆上动态分配内存
可变性 不可变(除非通过 &mut str,但极少用) 可变(支持修改、追加等操作)
生命周期 必须有生命周期(如 'static 或借用的作用域) 无生命周期(独立拥有数据)
典型用途 读取、传递静态字符串或现有字符串的切片 需要修改、动态构建或拥有所有权的场景

2. 为什么函数这样设计?

pub fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}
  • 参数用 &str
    函数不需要所有权,只需读取 name 的内容。&str 是轻量级的引用,避免不必要的内存分配或所有权转移。

  • 返回值用 String
    format!() 宏会生成一个新的 堆分配的字符串String),需要返回给调用者所有权。调用者可以自由使用或丢弃这个字符串。


3. 何时用 &str

  • 传递静态字符串(如硬编码的文本):
    let s: &str = "hello"; // 指向静态数据,无需分配内存
    
  • 读取 String 的切片(避免所有权转移):
    let name = String::from("Alice");
    greet(&name); // 传递 &str 切片(自动将 &String 转换为 &str)
    
  • 函数只需读取字符串(不修改、不存储):
    fn print_name(name: &str) {
        println!("Name: {}", name);
    }
    

4. 何时用 String

  • 需要修改字符串
    let mut s = String::from("hello");
    s.push_str(", world!"); // 只有 String 支持修改
    
  • 需要动态构建字符串(如拼接、格式化):
    let s = format!("{} + {} = {}", 1, 2, 1 + 2); // 返回 String
    
  • 需要长期存储或传递所有权
    fn create_message() -> String {
        String::from("This message will be owned by the caller")
    }
    

5. 关键转换规则

  • &strString(需要分配内存):
    let s: &str = "hello";
    let owned_s: String = s.to_string(); // 或 String::from(s)
    
  • String&str(零成本引用):
    let s = String::from("hello");
    let slice: &str = &s; // 自动解引用为 &str
    

6. 为什么 Rust 要区分它们?

  • 性能优化&str 避免不必要的内存分配,适合只读场景。
  • 所有权安全String 的独占所有权防止数据竞争和意外修改。
  • 接口清晰:通过类型系统明确函数是否需要所有权(String)或仅借用(&str)。

7. 实际示例对比

&str 作为参数(更灵活)

fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

fn main() {
    // 可以接受 &str 或 &String
    greet("Alice");          // 直接传递 &str
    greet(&String::from("Bob")); // 传递 &String(自动转为 &str)
}

String 作为参数(较少用)

fn greet(name: String) -> String {
    format!("Hello, {}!", name) // 转移所有权,name 在此函数后无法使用
}

fn main() {
    let name = String::from("Alice");
    greet(name); // 所有权转移给 greet,此处 name 不能再使用
    // println!("{}", name); // 编译错误:name 已被移动
}

总结

  • &str:当函数只需要读取字符串时(参数更通用,支持 &str&String)。
  • String:当函数需要修改字符串、动态构建字符串或获取所有权时。
  • 优先用 &str:除非需要所有权或修改,因为它的灵活性更高(零成本抽象)。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。