当前位置: 首页 > news >正文

rust中,str 和 String有什么区别和联系?

在 Rust 中,&strString 都用于处理文本,但它们在内存布局、所有权语义、使用场景上有本质区别。理解它们的差异是掌握 Rust 字符串处理的关键。


一、核心区别概览

特性 &str String
类型 字符串切片(引用类型 可变、可增长的字符串(拥有所有权的堆分配类型
内存位置 指向已有字符串数据(栈、堆、或静态存储) 数据存储在堆上
可变性 不可变(&str 是只读引用) 可变(可通过 push, push_str, insert 等修改)
生命周期 有生命周期(如 &'a str),依赖所引用数据的存活时间 自包含,拥有自己的数据,无生命周期参数
大小 固定大小(2 个字长:指针 + 长度) 动态大小(栈上存指针、长度、容量;堆上存实际字节)
是否可增长 ❌ 不能修改或增长 ✅ 可动态增长(类似 Vec<u8>
如何创建 字符串字面量、从 String 借用、切片操作 String::new(), String::from("..."), "...".to_string()

二、详细解释

1. &str:字符串切片(String Slice)

  • 是一个不可变的 UTF-8 字节序列的引用
  • 类似于 &[u8],但保证是合法 UTF-8
  • 最常见的形式是字符串字面量,其类型为 &'static str(生命周期为 'static
let s1: &str = "hello"; // 字符串字面量,'static 生命周期
let s2: &str = &"world"; // 等价
  • 也可以从 String 借用得到:
let owned = String::from("Rust");
let slice: &str = &owned; // 借用 String 的内容

&str视图(view),不拥有数据,只“看”数据。


2. String:堆分配的拥有型字符串

  • Vec<u8> 的 UTF-8 封装,拥有其数据
  • 可在运行时动态增长、修改
  • 通过 String::fromto_string()format! 等创建
let mut s = String::from("Hello");
s.push_str(", world!"); // 修改
s.push('!');            // 添加字符
println!("{}", s);      // "Hello, world!!"

String所有者(owner),负责管理堆内存。


三、联系与转换

1. String&str(免费、安全)

通过借用(Deref 强制转换):

let s = String::from("hello");
let slice: &str = &s;        // 显式借用
// 或直接传递给接受 &str 的函数:
fn print_str(x: &str) { println!("{}", x); }
print_str(&s);               // 自动 Deref 转换

💡 Rust 会自动将 &String 转换为 &str(因为 String 实现了 Deref<Target = str>)。


2. &strString(需要分配内存)

通过克隆数据到堆上

let slice = "hello";
let owned: String = slice.to_string();     // 方法1
let owned2: String = String::from(slice);  // 方法2
let owned3: String = slice.into();         // 方法3(利用 From<&str> for String)

⚠️ 这个过程涉及堆内存分配和字节拷贝,有运行时开销。


四、使用建议(最佳实践)

场景 推荐类型
函数参数(只读) &str(更通用,接受字面量和 String
需要修改或所有权 String
返回新字符串 返回 String
存储字符串 根据是否需要所有权选择:
- 不需要修改/共享 → &'static str(如配置常量)
- 需要拥有数据 → String

示例:函数设计

// ✅ 好:接受 &str,兼容字面量和 String
fn greet(name: &str) {println!("Hello, {}!", name);
}greet("Alice");           // 字面量 OK
greet(&my_string);        // String 借用 OK// ❌ 不推荐:强制调用者必须提供 String
fn greet_bad(name: String) { ... }

五、内存布局图示

&str:┌──────────────┐│ 指针 → "hello"(可能在静态区、栈或堆) ││ 长度 = 5     │└──────────────┘String:┌──────────────┐│ 指针 → 堆 [h, e, l, l, o] ││ 长度 = 5     ││ 容量 = 5     │└──────────────┘

六、总结

对比项 &str String
角色 视图(View) 所有者(Owner)
内存 不分配新内存 堆分配
可变
通用性 高(函数参数首选) 低(但功能强)
转换 String&str:免费
&strString:需分配

记住

  • “切片看,String 拥有”
  • 函数参数用 &str,返回新字符串用 String
  • 字面量是 &'static str

理解 &strString 的区别,是写出高效、安全、惯用 Rust 代码的重要一步。

http://www.jsqmd.com/news/118519/

相关文章:

  • 【Open-AutoGLM快捷键配置终极指南】:掌握高效AI编程的10个核心技巧
  • Excalidraw AI功能本地化部署的硬件要求
  • 揭秘Open-AutoGLM远程管控黑科技:如何实现毫秒级设备响应与零故障运行
  • 生成引擎优化(GEO)助力内容创作与用户体验协同提升的新方法
  • Excalidraw AI适用于哪些典型业务场景?
  • 你的数据分析副驾:百考通AI如何让洞察触手可及
  • Excalidraw AI增强投标方案呈现力
  • Excalidraw AI在敏捷会议中的即时绘图应用
  • Open-AutoGLM脚本库使用陷阱大盘点,90%新手都会踩的3个坑
  • 运维成本PK:三大MQ(RabbitMQ/Kafka/RocketMQ)谁更省心?
  • Excalidraw AI降低非设计人员的绘图门槛
  • 【Open-AutoGLM指令集优化全解析】:揭秘下一代AI编译器性能飞跃核心技术
  • 38、SharePoint开发:打包、部署与环境准备全解析
  • Excalidraw AI改善客户沟通体验
  • Open-AutoGLM远程控制配置实战指南(99%工程师忽略的关键细节)
  • Excalidraw AI防止敏感信息泄露的设计
  • 计算机专业大学生必备:6款AI神器半天5000字论文+真实参考文献!
  • RocketMQ vs Kafka:金融级场景下谁更适合做消息中间件?
  • 40、SharePoint开发准备:开发者仪表盘与相关操作指南
  • Excalidraw AI创建HR人力资源体系结构图
  • AI应用架构师实战:如何用AI智能体优化数据架构的成本效率?
  • 项目开发项目----SMP(软件制作平台)语言基础知识之九
  • 还在写代码?用Open-AutoGLM拖拽式设计AI流程,效率提升90%!
  • Open-AutoGLM配置避坑指南,90%新手都会犯的5个致命错误
  • (稀缺资料)Open-AutoGLM自动向量化内幕:90%工程师不知道的编译优化路径
  • Ceph基础原理分享
  • 激光熔覆中的 Comsol 模拟:熔池探秘与激光增材制造仿真
  • 如何用Open-AutoGLM脚本库缩短80%模型部署时间?真相在这里
  • sglang
  • TypeScript 中的模块(Modules)详解