Rust中的String与str:为什么新手会混淆以及如何一劳永逸地搞懂
\n\n如果你刚开始学习Rust,你肯定遇到过这种情况:编译器报错,你试图将String传递给期望&str的地方,或者反过来。熟悉吗?这是Stack Overflow上最热门的问题之一(成千上万的浏览量!),这并非偶然——这个话题对于理解Rust中的内存管理确实至关重要。
在本文中,我们将弄清楚String和&str的区别,何时使用哪种类型,以及如何避免典型错误。开始吧!
给赶时间的人的简短回答
\n\n如果你现在就需要答案——记住要点:
\n\n- \n
String— 是一个拥有所有权、可变、动态的数据类型,存储在堆(heap)上。 \n&str— 是一个不可变的字符串切片(slice),它引用属于其他人的数据。最常见的形式是&str。 \n
现在让我们深入探讨。
\n\n什么是Rust中的String?
\n\nString是一种拥有其数据的类型。当你创建一个String时,内存会在堆上分配,并且字符串可以增长、缩小或修改。
let mut s = String::from("Привет");\ns.push_str(", мир!");\nprintln!("{}", s); // 输出:Привет, мир!\n\n这里s是字符串的所有者。当s离开作用域时,内存会自动释放(感谢RAII——资源获取即初始化)。
String的主要特性:
\n- \n
- 拥有数据(owning type) \n
- 可变的(mutable) \n
- 存储在堆上 \n
- 可以从字符串字面量创建:
String::from("текст")\n - 支持拼接、插入、删除字符 \n
什么是Rust中的&str?
\n\n&str(读作“str切片”或“字符串切片”)是一个引用,指向属于其他人的UTF-8字符序列。&str本身只是一个指向数据的指针和长度。
let greeting: &str = "Привет";\nprintln!("{}", greeting);\n\n在这个例子中,greeting是对字符串字面量的引用,该字面量直接存储在程序的二进制文件中(在只读内存段中)。greeting不拥有这些数据——它只是指向它们。
&str的主要特性:
\n- \n
- 不拥有数据(borrowed type) \n
- 不可变的(immutable) \n
- 要么存储在二进制文件中(字符串字面量),要么存储在堆上(作为
String的切片) \n - 轻量级——由两个字段组成:指针 + 长度(在64位系统上为16字节) \n
- 当不需要修改字符串时,非常适合传递给函数 \n
String和&str的关键区别(表格)
\n\n让我们将所有内容汇总到一个清晰的表格中:
\n\n| 特性 | \nString | \n&str | \n
|---|---|---|
| 所有权 | \n拥有数据 | \n借用数据 | \n
| 可变性 | \n是(mut) | \n否 | \n
| 存储位置 | \n堆(heap) | \n堆、栈或二进制文件 | \n
| 栈上大小 | \n24字节(ptr + len + cap) | \n16字节(ptr + len) | \n
| 创建方式 | \nString::from("...") | \n"..." 或 &s[..] | \n
| 主要用途 | \n当需要修改或拥
博客书籍推荐推荐阅读 |