0Pricing
Learn Rust Coding · 课时

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. String 与 &str 的区别
  2. 切片
  3. 字符串方法
  4. UTF-8 与字符
← 返回 Learn Rust Coding