Rust入门进阶系列 | 理解Rust中的 String 和 &str

Rust 09: 字符串详解(String、&str、内存布局、常用方法) Rust中字符串相关String、&str的内存布局和常见用法。 阅读详情


前言

当你开始学习 Rust 编程时,你可能经常遇到字符串使用问题的编译错误,经常搞不懂String和&str什么时候使用,出现了又如何解决。

Rust 的字符串设计与大多数具有单一字符串类型的编程语言有所不同。Unicode 安全的字符串设计和独特的所有权机制都使 Rust 中的字符串对于初学者来说在某种程度上是违反直觉的。

这篇文章我们简单说一下String和&str是什么意思,代表什么含义,尤其是在什么时候使用哪一个类型。

理解这篇文章中涉及的概念将使您能够以更有效的方式使用 Rust 中的字符串,同时也可以更好地理解其他人的代码,因为您将更好地了解为什么做出有关字符串处理的某些决定的原因。


一、String的理解

String 是一个需要动态分配大小的,其大小在代码编译时是未知的,内部的容量是可以随时根据需要变化的。

从String的源码可以看到他的结构如下:

#[derive(PartialOrd, Eq, Ord)]
#[cfg_attr(not(test), rustc_diagnostic_item = "String")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
    vec: Vec<u8>,
}

我们可以通过多种方式创建一个String:

let s = String::new()         // An empty String
let s = "Hello".to_string();
let s = String::from("world");
let s: String = "also this".into();

Rust 的字符和字符串类型是围绕 Unicode 设计的。 String不是 ASCII 字符序列,而是 Unicode 字符序列。Rust 类型是一个包含 Unicode 代码的 32 位值。 String使用 UTF-8 将 Unicode 字符编码转为vec。

let hello = String::from("こんにちは");
let hello = String::from("안녕하세요");
let hello = String::from("你好");

字符串中的.len()方法将返回以字节为单位的长度,而不是以字符为单位的长度。

assert_eq!("ಠ_ಠ".len(), 7);
assert_eq!("ಠ_ಠ".chars().count(), 3);

而字符串都没有index的索引操作

由于 UTF-8 是一种可变宽度的编码格式,因此字符串中的每个 ASCII 字符都存储在一个字节中,而其他字符可能占用多个字节。因此,在这种格式中,字符串字节的索引并不总是与有效的 Unicode 标量值相关。

如果想更方便地修改一个 String中的特定字节,则需要将其转换为vec<u8>:

fn set_char_inplace(text: &mut String, index: usize, c: char) {
    let bytes = unsafe { text.as_mut_vec() };
    bytes[index] = c as u8;
}

String可以从另一个方面理解成是一个字节的集合和一些集合的操作方法,存储了一串UTF-8编码的文本。

Rust 中的字符串保证是有效的 UTF-8,可以参考这篇文章的说明Rust为什么要使用UTF-8UTF-8 Everywhere (utf8everywhere.org)

二、什么是&str

str是Rust语言原始类型,也可以称为string slice,通常以借用的方式出现&str

let a: &str = "hello rust";
//it is same with below
let a: 'static str = "hello rust";
// 'static 是一个静态变量,生命周期贯穿整个代码执行
// &str 一般不可直接修改

通常这种都叫做胖指针,胖指针一般有两部分组成:指向bytes的指针和长度

可以通过as_ptr()方法和len()方法获取对应的值

let story = "Hello world";

let ptr = story.as_ptr();
let len = story.len();

 三、String和&str

Rust中的String和&str,就像C++中的std::string和char*:

  • String 拥有所有内存相关的操作,可以对字符串做很多的处理
  • &str 有包含长度

&str包含长度,是因为在操作时候可以使用&str获取到String中的任意一段的内容,例如:

pub fn main() {
    let s: String = String::from("hello");
    let a: &str = &s;
    let b: &str = &s[1..3];
    let c = "beaf";
    println!("a: {}, len: {}", a, a.len());
    println!("b: {}, len: {}", b, b.len());
    println!("c: {}, len: {}", c, c.len());
}

 

四、String 还是 &str ?,该如何选择?

 一般要遵循两个原则:

  • 当您需要拥有内存时使用String。例如,您在函数中创建了一个字符串,需要各自操作,需要返回它。

  • 当您需要对 String 变量(或代码中的字符串文本)的不可变引用时使用&str,一般只是引用不会对其修改或其他操作

请记住,当String您将其作为参数传递给函数时,Rust 将遵循move语义原则

fn func(a: String) {
    println!("{}", a);
}

pub fn main() {
    let v = String::from("hello");
    func(v);
    println!("v: {}", v);
}

这段代码会出现报错

对于上面一段代码 v 已经move到了func里面,在Rust中可以使用Rust语言的 deref coercing

将&String 转成 &str。如果使用&str,可以修改成:

fn func(a: &str) {
    println!("{}", a);
}

pub fn main() {
    let v = String::from("hello");
    func(&v);
    println!("v: {}", v);
}

所以当我们在设计一个API或者方法如果只是对字符串的只读操作,最好还是使用&str

但是当你需要修改一个String的内容时,并不能通过&mut str修改 ,虽然确实存在,但它不是很有用,因为切片无法重新分配其引用。当你需要修改字符串的内容时,需要&mut String作为参数传递,就像上面提到的set_char_inplace例子一样。

在struct中使用字符串时,通常需要修改或操作字符串,最好使用String,但是也可以使用str,只是需要注意rust里面的生命周期是否正确

struct Person<'a> {
    name: &'a str,
}
impl<'a> Person<'a> {
    fn greet(&self) {
        println!("Hello, my name is {}", self.name);
    }
}
fn main() {
    let person = Person { name: "Coder's Cat" };
    person.greet();
}

 
    
Rust中String与&str的区别及内存管理实践 在编程语言中,字符串处理是基础但关键的技术点。Rust语言通过String和&str两种类型的区分,完美体现了其所有权系统的设计哲学。String作为可变的堆分配字符串,拥有数据所有权;而&str作为不可变字符串切片,实现了零成本的借用机制。这种设计不仅保证了内存安全,还通过编译期的借用检查避免了数据竞争。在实际工程中,理解UTF-8编码、内存布局和生命周期管理等概念,能帮助开发者编写高性能且安全的Rust代码。特别是在网络编程、系统开发和性能敏感场景中,合理选择字符串类型能显著提升程序效率。 阅读详情

相关推荐

Rust字符串操作全解析:从String与&str区别到高效处理方法

在系统编程中,字符串处理是基础且关键的技术环节,涉及内存管理、编码格式和性能优化等多个核心概念。Rust语言通过String和&str两种类型的协作设计,实现了内存安全与零成本抽象的平衡。String作为可变的、拥有所有权的堆分配缓冲区,适用于需要修改或长期持有的场景;而&str作为不可变的字符串切片,提供了轻量级的文本视图,常用于函数参数传递和临时引用。这种设计不仅确保了UTF-8编码的安全性,还通过所有权机制避免了常见的内存错误。在实际开发中,理解两者的转换时机、掌握format!宏的灵活拼接、以及合理

weixin_34161083的博客 308

一文解决Rust字符串:String,str,&String,&str,CString,CStr

而str是一个不可变的固定长度的字符串,如果是从String解引用而来的,则指向堆上,如果是字面值,则指向静态内存。在Rust中,s的类型是&str,而“abcd”是str类型,这里的“abcd”就是字符串字面值,存放在Stack上的。s 是切片,切片是一个结构体,包含两个字段,一个是指向数据的指针,另一个是数据的长度。和CStr表示从C中来,rust不拥有归属权的字符串相反,CString表示由rust分配,Rust拥有所有权,可以进行修改,用以传给C程序的字符串。表示的类型有很多种。

phthon1997的博客 4498

详解Rust 中 String 和 str 的用途与区别

String是一个功能强大的动态分配的堆内存字符串类型。可变性:这是String类型的一个关键特性,它支持动态修改。这意味着你可以在程序运行过程中对字符串进行各种操作,包括添加新的字符、删除已有的字符,或者替换其中的部分字符。例如,你可以在一个已有的字符串后面追加新的文本,或者从中间删除一些字符,以满足不同的业务需求。所有权:在Rust的所有权系统中,String拥有字符串数据的所有权。这意味着它负责管理字符串数据的生命周期,包括在适当的时候释放其所占用的内存资源,以避免内存泄漏等问题。

1225

Rust - 字符串:&str 与 String

总的来说,String 和 &str 在 Rust 中提供了灵活的字符串处理机制,允许你根据需要选择最合适的类型。String 提供了可变性和动态内存管理,而 &str 提供了对字符串数据的不可变引用,这两者在不同的场景下都非常有用。

日拱一卒无有尽,功不唐捐终入海 2124

[Rust进阶篇]-Rust之&str与String比较及转换方法使用总结

1.&str与String区别 1) &str类型是Rust语言的原生类型,它指向分配在某处的String的一个*固定*容量,这里又分为2类: a 如果&str指向的是String类型,由于String创建于堆区,则&str指向堆。 b 如果&str指向的是字面量字符串(&str),则&str指向的是静态区内存。 2) Rust中,字符串(&str和String)Unicode 标量值的序列编码为 utf - 8 字节的流 3) &

图解AI 6568

FPGA网络调试实战:基于88E1111和DP83867两款PHY芯片的SGMII-UDP数据回环对比与避坑指南

本文深入对比了88E1111与DP83867两款PHY芯片在SGMII-UDP数据回环中的性能差异,涵盖硬件设计、Vivado工程配置及调试技巧。通过实测数据揭示DP83867在吞吐量、延迟和功耗方面的优势,并提供FPGA网络调试中的常见问题解决方案,助力工程师高效完成项目开发。

weixin_31682031的博客 384

rust 中的 String 和 &str

1.str和 &str 看下面的代码: let s = "hello"; 其中,"hello"的数据类型是str,变量 s的数据类型是 &str。有点难理解,我们可以与c语言比较,然后就容易理解了。上面的代码在c语言中是下面的样子: char *s = "hello"; 很有意思吧?在c语言中,s是指针。但是,变量s用起来很不安全,因为不知道 s指向的数据占用了多少内存空间。 于是在rust中,s是切片。切片是一个结构体,包含两个...

程序猿视角 5744

涨薪技术|Kubernetes(k8s)环境部署实战

这两者都是在/etc/docker/daemon.json里修改的,所以我们一起配置了就好了,首先执行下述命令编辑daemon.json:​​​​​​​。安装完成后,可以使用以下命令来查看dashboard访问的端口号​​​​​​​。网络插件CNI也是以容器的方式进行启动​​​​​​​。安装完成后可以检查是否拉取了对应的容器​​​​​​​。再使用以下命令进行安装:​​​​​​​。打开后输入以下内容:​​​​​​​。安装1.19.0版本​​​​​​​。修改IP地址:​​​​​​​。

m0_60889254的博客 1085

深入解析 Rust 中的 String 与 &str:从内存布局到性能优化的全面对比​​

本文深入解析Rust中String与&str的核心差异。String是堆分配的可变字符串类型,拥有数据所有权;&str是字符串切片,作为不可变视图引用内存中的UTF-8数据。从内存模型看,String封装Vec<u8>进行动态堆分配,而&str是仅包含指针和长度的胖指针。性能上,&str创建零成本,适合高频只读场景;String的clone是深拷贝,代价较高。最佳实践包括:函数参数优先用&str,数据结构按需选择所有权,避免返回局部&str。

2501_94022820的博客 1074

WIN10系统下VS2019编译CloudCompare2.12.4

CloudCompare2.12.4

点云侠的博客 3143

B07:AI 时代怎么考核团队?我把 KPI 改了 5 版才找到答案

最后说一句掏心窝的话。绩效考核不是"管人"的工具,是"引导团队行为"的工具。你定什么指标,团队就会做什么行为。你定"AI 占比",团队就凑占比你定"效率提升",团队就挑软柿子你定"代码行数",团队就刷行数你定"工具使用率",团队就刷使用只有定"业务价值 + 工程质量 + 能力成长"三个维度的指标,团队才会真正关注长期价值。这套 KPI,我在我带的团队里跑了 6 个月,没有任何一个指标被"刷"出来。考核的是结果,不是过程。永远考核"创造了多少价值",永远不考核"用了多少 AI"。

刘一说的IT专栏 502

Rustlings Rust 字符串指南:识别、创建与使用 &str 和 String 两大字符串类型

本文围绕 rustlings 练习集 `09_strings` 模块展开,系统讲解 Rust 的两种字符串类型——字符串切片(`&str`)与拥有所有权的字符串(`String`):如何识别一个值的类型、如何用 `String::from`、`.to_string()`、`format!` 等方式创建字符串、`&String` 到 `&str` 的自动类型强制转换(deref coercion),

gitblog_00336的博客 781

RD算法(一)初出茅庐 —— 算法原理

在《SAR成像概述》的第4节已经对各种SAR成像算法进行了一个简要的概述,本文就直接从RD算法讲起了。

5288

Rust 深度剖析:String 与 &str 的内存布局与实现差异

在 Rust 中,String和&str(字符串切片) 是处理文本的两个基本类型。初学者常常对何时使用它们感到困惑,而这种困惑的根源在于它们。String是所有者,而&str是借用者。这种差异体现在它们的数据结构、内存位置和核心职责上。

kelvislawyer的博客 846

【从零开始学习SLAM】官方tf教程小海龟跟随程序

ros tf 进行坐标系之间转换的运算和发布

小秋 AI SLAM 入门实战教程 2033

2022年8月27日全国青少年信息素养大赛Python编程小学组决赛真题+答案解析

2022年8月27日全国青少年信息素养大赛Python编程小学组决赛真题+答案解析

伶俐角少儿编程 454

Rust Koans字符串篇:彻底分清String与&str的8个关键差异及避坑指南

Rust Koans 是一套通过"填空式测验"带你逐步掌握 Rust 语言的交互式教程,而字符串篇正是许多新手卡壳的第一关。不少初学者刚接触 Rust 字符串时,都会被 `String` 与 `&str` 这两个类型绕晕:为什么有的能修改、有的不能?为什么两个 `String` 拼接还要额外加一个 `&` 符号?本文基于 Rust Koans 中的 [string.rs](https://link

gitblog_01191的博客 239

【功能安全】【AutoSAR】程序流监控机制

目录 一、程序流执行的常见故障 二、程序流的监控机制 1、监控功能的实现 2、三种监督机制 a、生命监测机制 b、截止时间监测机制 c、逻辑程序流监测机制 一、程序流执行的常见故障 与程序流相关的故障,在ISO26262中第六章附录D中定义如下: — 执行阻塞; — 死锁; — 活锁; — 执行时间的不正确分配; — 软件要素间的不正确同步。 二、程序流的监控机制 1、监控功能的实现 AutoSAR中对程序流的监控功能的实现主要有“看门狗”栈(Watchdog Stack).

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 4518

【 Rust探索】字符串类型(String与&str)的转换与常用方法

/ 创建空 String// 从字符串字面量创建 Stringlet s2 = String::from("编程");// &str 字面量let slice: &str = "入门";// 拼接println!// 输出:Rust编程入门本案例全面介绍了 Rust 中最重要的两种字符串类型 ——String和&str,并通过丰富的代码示例、对比表格和学习路径,帮助读者建立起对 Rust 字符串系统的深刻理解。本质区别String是拥有所有权的堆字符串,而&str。

IRonSir 952

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

rust-by-practice 复合类型实战:彻底掌握 Rust 字符串(str / &str / String)的类型体系、转换与 UTF-8 操作

本指南以 [rust-by-practice](https://link.gitcode.com/i/532f950910c09cec930d8f69b67316c0) 仓库中「复合类型」章节的[字符串练习](https://link.gitcode.com/i/2760b2a31cd324449083bf09bdec9e5d)为骨架,系统讲解 Rust 中 `str`、`&str`、`Strin

gitblog_00426的博客 677

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Rust 字符串性能:String、&str、Cow 的选择不是随便来的

str:零成本引用,能用就用。解析、匹配、切片首选。String:需要拥有所有权或修改内容时用,记得预分配。Cow<str>:不确定要不要改的时候用,写时复制,延迟分配,性能利器。:编译期确定的常量,直接硬编码在二进制文件中。这些概念在我刚开始学 Rust 时确实觉得繁琐,但用熟了之后才体会到:Rust 逼迫你在写代码时就思考内存布局,而这些思考换来的就是运行时的零开销和高性能。自学出身不可怕,怕的是不求甚解。

no1coder的博客 4649

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Rust之String与&str的内部实现差异的理解

核心差异对比特性String&str内存位置堆堆/静态区/栈所有权拥有借用可变性可增长不可变大小24字节16字节性能涉及分配零拷贝最佳实践口诀函数参数用 &str:接受更多类型 🎯需要所有权用 String:构建/修改字符串 ✏️避免不必要转换:理解零成本抽象 🚀注意 UTF-8 边界:切片索引需谨慎 ⚠️理解这些内部实现,你就能写出既安全又高性能的 Rust 代码!💪✨。

iblue007的博客 405

【rCore OS 开源操作系统】Rust 字符串(可变字符串String与字符串切片&str)

Rust 开源操作系统训练营:熟练掌握 Rust 的字符串类型——可变字符串 String 和字符串切片 &str

碳基蒟蒻Serio的博客 1924

深入理解 Rust 的 String 与 &str:内部实现与实践思考

Rust中的String和&str代表两种不同的字符串处理策略:String是堆分配的可变字符串,拥有所有权和扩容能力;&str是不可变切片引用,实现零拷贝但无法修改。从内存所有权看,String需负责释放资源,而&str必须依赖被引用对象的生命周期。性能层面,String适用于动态构建,&str适合高效读取。在API设计中,优先使用&str类型参数能提升灵活性并减少拷贝开销。这两种类型的差异体现了Rust所有权模型的核心思想——通过明确的类型区分实现安全与性能的平衡

2301_80396173的博客 447

Rust 内存语义深度解析:String 与 &str 的内部实现差异

Rust中String与&str的核心区别在于所有权模型:String是堆分配的可变字符串,拥有数据所有权;&str是轻量级不可变引用,指向现有字符串数据片段。String需要内存分配管理,而&str实现零拷贝访问。这种设计体现了Rust的所有权系统哲学,兼顾性能与安全:动态修改时使用String,只读访问时优先&str。实践中应遵循"最小约束原则",函数参数优先接收&str,仅在需要所有权时使用String。这种区分使Rust既能保证内存安全,又

tan_dan_zhuanshu的博客 621

Rust知识点——String与&str的内部实现差异

String 与 &str 的差异不仅仅是语法层面的选择,更是 Rust 内存安全与性能权衡的缩影。String 用堆内存和所有权换取了可变性和灵活性,&str 用不可变性和借用换取了零成本的高效传递。真正的 Rust 专家,会根据具体场景在这两者间做出精准的选择:在接口设计中优先使用 &str 来保持通用性和性能,在内部实现中使用 String 来管理动态数据。这种对内存语义的深刻理解,正是编写高性能、零成本抽象的 Rust 代码的关键所在。🦀💪。

2301_79779252的博客 498
上一篇: Node.js 构建一个 Rust 应用图片处理应用
松_
博客等级 码龄15年 2粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

松_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值