String 与 &str 的区别
文本的所有权
String 与 &str 的区别 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
拥有的文本与借用的文本
Rust 将文本所有权分为两种类型:
String— 在堆上拥有自己的数据。&str— 借用一段自己不拥有的文本视图。
fn main() {
let owned = String::from("I own this");
let borrowed: &str = "I am borrowed";
println!("{} / {}", owned, borrowed);
}数据存储在哪里
String 将其字节存储在堆上,并且可以增长。字符串字面量 &str 已嵌入程序二进制文件中,大小固定。
fn main() {
let mut heap = String::from("grows");
heap.push_str(" bigger");
let fixed = "never changes";
println!("{} | {}", heap, fixed);
}所有权意味着责任
String 的所有者在其离开作用域时释放内存。&str 不拥有任何数据,因此不会释放任何内容。
fn main() {
{
let s = String::from("temporary");
println!("{}", s);
} // s is dropped and its memory freed here
println!("done");
}借用 String
您可以使用 & 将 String 借用为 &str。String 仍然拥有这些数据;切片只是查看它。
fn main() {
let owned = String::from("shared text");
let view: &str = &owned;
println!("{} / {}", owned, view);
}移动 String
将 String 赋值给另一个变量会移动所有权。原变量将无法再使用。
fn main() {
let a = String::from("hello");
let b = a; // ownership moves to b
// println!("{}", a); // would error: a was moved
println!("{}", b);
}通过克隆保留两份
如果需要两个彼此独立的拥有所有权的字符串,请使用 clone 复制数据。
fn main() {
let a = String::from("hello");
let b = a.clone();
println!("{} and {}", a, b);
}复制 &str 的成本很低
&str 实际上只是一个指针和一个长度,因此复制它不会复制底层文本。它实现了 Copy。
fn main() {
let original = "data";
let copy = original; // both still valid
println!("{} {}", original, copy);
}函数与所有权
按值传递 String 会将其移动到函数中。传递 &str 或 &String 只会进行借用,因此调用者仍可使用原来的值。
fn length(s: &str) -> usize {
s.len()
}
fn main() {
let text = String::from("measure me");
println!("{}", length(&text));
println!("still here: {}", text);
}返回拥有所有权的字符串
当函数必须生成新文本时,应返回拥有所有权的 String,这样调用者就能取得所有权。
fn make_greeting(name: &str) -> String {
format!("Hello, {}!", name)
}
fn main() {
let g = make_greeting("Rust");
println!("{}", g);
}选择正确的类型
指导原则:
- 要存储拥有所有权的文本?使用
String。 - 只读取或传递文本?接受
&str。 - 在函数中构建新文本?返回
String。
fn first_word(s: &str) -> &str {
s.split_whitespace().next().unwrap_or("")
}
fn main() {
let sentence = String::from("learn rust today");
println!("{}", first_word(&sentence));
}为什么这种区别很重要
这种区分让 Rust 无需不必要的复制即可运行,并且无需垃圾回收器也能保证内存安全。您始终清楚一段文本由谁拥有。
fn main() {
let owned = String::from("safe");
let borrowed = &owned[..];
println!("owner {} borrows {}", owned, borrowed);
}快速检查
回顾移动 String 时会发生什么。
总结
String 与 &str 的所有权:
String拥有堆上的数据,并在被丢弃时释放这些数据。&str借用已有文本,不拥有任何数据。- 移动 String 会使原变量失效;
clone会复制它。 - 读取文本时接受
&str,生成新文本时返回String。
fn shout(s: &str) -> String {
s.to_uppercase()
}
fn main() {
let name = String::from("rust");
let loud = shout(&name);
println!("{} -> {}", name, loud);
}常见问题解答
「String 与 &str 的区别」课时是免费的吗?
是的 — 「String 与 &str 的区别」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「String 与 &str 的区别」这节课中我会学到什么?
文本的所有权 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「String 与 &str 的区别」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。