前言
前面学习了 Rust 基础语法后,你会频繁遇到 String 这个类型——它与 Rust 的核心概念所有权紧密相关。
本文会先从 String / &str 入手,讲清所有权与借用,再补充一组常用的 String API,方便后续章节查阅。
字符串浅析
从比较宏观的角度去看你经常接触到的软件可以发现,对于控制台程序,你看到的只有字符。
而对于有图形界面的软件(GUI),除了图案、就是各种文字了(字符串)。
从这你便能看出字符串的重要性:无论什么程序,基本都离不开字符串的使用。
在rust中使用字符串,可以用以下代码:
方式是用String这个crate(箱子、包)中的from函数,来从一个字面量hello world得到一个字符串String类型:

那看到这里你可能觉得有些奇怪了,明明我直接等于一个字符串字面量也可以呀!
比如像下面这样:
这确实是没问题的,但如果你看到编译器自动推导的类型就会发现,此刻的s已经不是String类型了

是不是觉得很奇怪!这里的是&'static str类型,并不是字符串String类型。
这里我们先不管这两个类型之间的区别,仅从现象上看就能说明,字符串字面量的类型就是&' static str
因为编译器推断s的类型是通过右边的字面量来推断的,既然是s是&' static str类型,那么右边的字面量肯定也是&'static str类型才对。
那么就此可以推断出,String::from这个函数的作用就是将一个字符串字面量&'static str类型转换为String类型。
因为经由这个函数之后,编译器就推断出s为String类型了。
注意这个'static的前缀,它实际上并不是类型、而是生命周期标注,static意味着它是静态的、全局可用的,所以其更简洁的类型表示实际上是&str。
那么这两种类型有什么区别呢?
目前来看,最直观的区别就是:String类型是可变的,而&str类型是不可变的。
比如下面的代码:
即使你添加了mut关键字,对于&str类型,仍然是不可变的。
对于字符串的+运算符,会将后面的字符串追加到第一个字符串并返回,比如s+"test",就是尝试将"test"追加到s之后、并返回拼接的结果,如果s不可变,那么就会拼接失败。
原因在于mut指代的是s本身可变,比如你完全可以让s等于一个新的字符串:
下面我们就要开始分别深度探讨两个几个问题:
String类型与&str类型到底代表什么意思?- 为什么两者会有这个特性?
只要搞懂了这两个问题,你对于rust的设计理念认知便又进了一大步,这对于之后的学习是很有帮助的。
因为除了字符串之外,其它很多地方都会用到这个特性,这并非是字符串所独有的。
&str与String
首先看到第一个问题: String类型与&str类型到底代表什么意思?
我们要知道&这个符号是可以剥离出来的,实际上应该是:String与str。
如何你对C++熟悉的话,那么可以认为&基本就等价于C++中的引用。
其中String代表一个可独立操作的字符串,也就是说,它拥有一个字符串的所有权力,比如下面这段代码:
此时变量s就完全拥有了操作这个字符串"hello world"的权利,增、删、改、查均可以,一旦你这个变量s没有了,那么"hello world"这个字符串同样也会在消失,两者是彻底绑定在一起的。
而str这个类型,其意义仅在于你可以用它,比如打印,遍历,查看等等,除此之外,它对字符串本身根本做不了任何改变,因为它不拥有这个字符串。
比如上面这段代码,即使a变量消失了,这个字符串"hello world"实际上仍然在内存中,并没有消失,因为a并不拥有这个字符串。
所以如果你想要修改一个str类型的变量,你就必须先将其转换为String类型
这个to_string的原理是,将a所指向的字符串复制一份并交由s,然后s就拥有了字符串副本的所有权,可以任意增删改查。
如果想要将String转换为str也是可以的,并且更加的简单:
就像上面那样,你只需要通过[0..2]的方式表达一个范围,比如这里的意思就是s中0到2范围的子字符串,然后前面添加一个&,就可以将其转换为str类型,并交给s1。
此时s1就为子字符串:he。
因为下标是从0开始的,到下标2的位置,但不包含2,如果用区间表示就是左闭右开:[0,2)
注意,在创建str类型时必须要在前面添加&符号,代表引用,因为它不拥有该字符串。
其意义在于它可以使用,但不能修改,并且其本身不与该字符串有其它任何权利关系。
事实上,它有一个更加官方的说话,叫做slice(切片)。
也因此,str类型都不能单独存在,而是结合&符号一起出现。
事实上并不仅仅是str,所有切片类型都只能与&符号共存,原因就在于它们没有内存的所有权,仅仅是引用。
以上就是对第一个问题的简要探究,下面我们再来看看第二个问题: 为什么两者具有这种特性?
这里所说的特性,指的是String对字符串拥有所有权,而str类型没有所有权,明明就一个字符串类型而已,为什么要拥有两种类型呢?
在第一章提到过,rust这门语言的目的是简化编程的同时,尽可能地提高程序运行效率。
而程序运行过程中,最影响效率的地方就是内存拷贝问题。
如果你学过C/C++、乃至其它语言,应该都多多少少听说过堆栈的概念。
前面我们提到过,我们的应用程序实际上都是运行在电脑内存里面的,虽然同样是内存,但为了方便程序使用,我们会人为的给某些内存定义为栈、某些内存定义为堆
这个涉及系统底层架构原理,比如栈就有一个专用的寄存器来表示,但对于写程序的我们来说,并不需要了解太多。
请开通后继续阅读后续 70% 并运行完整示例~