就字符串字面量来说,编译的时候就已经知道内容,所以文本就被直接硬编码进最终的可执行文件中。这样的做法使得字符串字面值快速且高效。不过这些特性都只得益于字符串字面量的不可变性。不幸的是,我们不能为了每个在编译时大小位置的文本将一块内存放进二进制文件中,并且它的大小可能随着程序运行而变化。
对于String 类型,为了支持一个可变、可增长的文本片段,需要在堆上分配一块在编译时未知大小的内存来访内容。这意味着:
String时将内存返回给分配器的方法第一部分由我们完成:当调用String:from时,它的实现(implementation)请求所需的内存。这在编程语言中是很常见且很通用的。
然而第二部分就有些不一样了。在很多有垃圾回收 的语言中,GC记录并清除不在使用的内存,而且开发者基本上不用关心这些内存的使用情况。在大部分没有GC的语言中,识别出不再使用的内存并调用代码显式释放就是我们必须要关心的事情了。从历史的角度上来说,正确的处理内存回收曾是一个困难的编程问题。如果忘记回收会出现内存浪费(内存泄漏),但如果回收过早就会出现无效变量,如果重复回收也是一个BUG,所以我们需要精准的为allocate配对一个 free。
相对其他语言,Rust采用了不同的策略:内存在拥有它的变量离开作用域之后就会被自动释放,下面的例子中就提及了一个作用域中使用String而不是字符串字面量值的情况。
{
let s = String::from("hello");//这里的s是有效的
//使用
s.push_str(",world");
}
//离开作用域 s 失效
这是一个将 String 需要的内存返回给分配器的很自然的位置:当 s 离开作用域的时候。当变量离开作用域,Rust 为我们调用一个特殊的函数。这个函数叫做drop,在这里 String 的作者可以放置释放内存的代码。Rust 在结尾的 } 处自动调用 drop。
| 🔙上一页 | 内存和分配🔜 |