深入理解Rust的字符串系统:str vs String、UTF-8编码、字符串操作和性能优化。
fn main() {
// &str — 字符串切片(借用)
let s: &str = "hello"; // 字面量,只读
let slice: &str = &s[..3]; // 切片
// String — 堆分配,可增长
let mut s = String::new();
s.push_str("hello");
s.push('!');
// 创建方式
let s1 = String::from("hello");
let s2 = "hello".to_string();
let s3 = format!("{} {}", "hello", "world");
// &str ↔ String
let owned: String = "hello".to_string();
let borrowed: &str = &owned;
}
✅ 编译验证通过
fn main() {
let hello = "你好世界";
// ❌ 不能用数字索引字符串!
// let ch = hello[0]; // 编译错误
// ✅ 字节切片(危险!)
let bytes = hello.as_bytes();
println!("字节: {:?}", bytes);
// ✅ 字符迭代
for ch in hello.chars() {
println!("字符: {}", ch);
}
// ✅ Unicode标量值
println!("字符数: {}", hello.chars().count());
println!("字节数: {}", hello.len());
// ⚠️ 字符数≠字节数≠显示宽度
let emoji = "🦀";
println!("🦀: 字符={} 字节={}", emoji.chars().count(), emoji.len());
}
✅ 编译验证通过
fn main() {
let mut s = String::from("hello");
// 追加
s.push_str(", world");
s.push('!');
// 拼接
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // s1被消耗!
// 插入/删除
let mut s = String::from("hello");
s.insert(5, '!'); // "hello!"
s.remove(5); // "hello"
s.replace_range(..1, "H"); // "Hello"
// 替换
let s = "I like Rust".replace("Rust", "Python");
// 分割
let parts: Vec<&str> = "a,b,c".split(',').collect();
let words: Vec<&str> = "hello world".split_whitespace().collect();
// 修剪
let trimmed = " hello ".trim();
// 大小写
let upper = "hello".to_uppercase();
let lower = "HELLO".to_lowercase();
}
✅ 编译验证通过
fn main() {
// 预分配容量
let mut s = String::with_capacity(100);
for i in 0..10 {
s.push_str(&format!("line {}\n", i));
}
// 避免频繁分配
// ❌ 每次都分配
let result = (0..100)
.map(|i| format!("{}", i))
.collect::<Vec<_>>()
.join(",");
// ✅ 使用write!
use std::fmt::Write;
let mut buf = String::with_capacity(200);
for i in 0..100 {
write!(buf, "{},", i).unwrap();
}
}
✅ 编译验证通过
实现一个简单的CSV行解析器,处理引号和转义。
实现Boyer-Moore字符串搜索算法。
实现简单的模板替换:{{name}} → 实际值。
掌握Rust字符串系统——UTF-8的正确处理方式
系统编程的核心挑战是在不牺牲安全的前提下获得最大性能。Rust如何实现这个目标:
所有权系统在编译期确定每个值的生命周期,不需要运行时垃圾回收。这意味着:无停顿、可预测延迟、更少内存占用。
泛型单态化、内联、LLVM优化——高级代码编译为与手写C相当的机器码。
Send/Sync trait在编译期保证:如果是并发访问,要么只读,要么互斥。数据竞争不可能发生。
| 特性 | Rust | C | C++ |
|---|---|---|---|
| 内存安全 | ✅ 编译期 | ❌ 手动 | ⚠️ 部分RAII |
| 线程安全 | ✅ 编译期 | ❌ | ❌ |
| 无GC | ✅ | ✅ | ✅ |
| 零成本抽象 | ✅ | ⚠️ 宏 | ✅ 模板 |
| 包管理 | ✅ Cargo | ❌ | ⚠️ vcpkg |
| 学习曲线 | 陡峭 | 中等 | 极陡 |
即使Rust保证内存安全和线程安全,仍需注意:
以下资源帮助你深入学习本课主题:
本课涉及的核心概念,确保你理解每一个:
| 术语 | 说明 |
|---|---|
| 所有权 | Rust内存管理的核心机制,每个值有唯一所有者 |
| 借用 | 通过引用访问数据,不获取所有权 |
| 生命周期 | 引用有效的范围,编译期分析工具 |
| trait | Rust的接口/抽象机制,类似其他语言的接口 |
| 泛型 | 参数化类型,零成本抽象 |
| 模式匹配 | 强大的数据解构和分支机制 |
| 零成本抽象 | 高层抽象不引入运行时开销 |
| fearless concurrency | 编译器保证线程安全 |
Q: Rust学习曲线真的很陡吗?
A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。
Q: Rust适合什么项目?
A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。
Q: 遇到编译错误怎么办?
A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。