Rust中的&str与String用法举例
【摘要】 在 Rust 中,&str 和 String 是两种不同的字符串类型,分别用于不同的场景。以下是它们的区别和适用场景: 1. 核心区别特性&str(字符串切片)String(可增长字符串)所有权借用(不拥有数据,只是引用)拥有数据(独占所有权)内存分配通常指向静态数据或已分配的内存(如 String 的切片)在堆上动态分配内存可变性不可变(除非通过 &mut str,但极少用)可变(支持修改...
在 Rust 中,&str 和 String 是两种不同的字符串类型,分别用于不同的场景。以下是它们的区别和适用场景:
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. 关键转换规则
&str→String(需要分配内存):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)