MST
星途 面试题库

面试题:Rust中字符串管理与所有权转移

假设有一个函数接收一个字符串字面量并将其传递给另一个函数,详细说明这个过程中所有权是如何转移的,以及内存是如何管理的。如果其中涉及字符串拼接操作,又会对内存管理产生什么影响?
15.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 所有权转移
    • 当一个函数接收一个字符串字面量并将其传递给另一个函数时,在 Rust 语言中,字符串字面量具有 &str 类型,它是一个借用类型。调用函数时,所有权不会转移,只是将对字符串数据的引用传递给被调用函数。例如:
    fn receive_string(s: &str) {
        // 这里只是借用了字符串,原字符串的所有权仍在调用者手中
    }
    fn main() {
        let s = "hello";
        receive_string(s);
        // 这里 `s` 仍然有效,因为所有权未转移
    }
    
    • 如果传递的是 String 类型(可增长的字符串),所有权会转移到被调用函数。例如:
    fn receive_string(s: String) {
        // 这里 `s` 获得了原 `String` 的所有权
    }
    fn main() {
        let s = String::from("hello");
        receive_string(s);
        // 这里 `s` 不再有效,因为所有权已转移
    }
    
  2. 内存管理
    • 对于字符串字面量(&str),其内容存储在程序的只读数据段,生命周期与程序相同。函数调用时只是传递指向这个只读数据段的指针,不会进行额外的内存分配或释放操作。
    • 对于 String 类型,它在堆上分配内存来存储字符串内容。当所有权转移时,堆上的内存也随之转移,原所有者不再能访问这块内存。当 String 离开作用域(例如在函数结束时),它会自动释放堆上分配的内存。
  3. 字符串拼接操作对内存管理的影响
    • 如果使用 + 运算符或 format! 宏等方式进行字符串拼接,会创建一个新的 String。例如:
    let s1 = String::from("Hello, ");
    let s2 = String::from("world!");
    let s3 = s1 + &s2;
    
    • 这里 s1 的所有权被转移到 s3 中,s2 只是被借用。s3 会在堆上分配足够的内存来存储拼接后的字符串内容。如果拼接操作频繁进行,会导致频繁的内存分配和释放,影响性能。在这种情况下,可以考虑使用 String::with_capacity 预先分配足够的内存,减少重新分配的次数。例如:
    let mut s = String::with_capacity(s1.len() + s2.len());
    s.push_str(&s1);
    s.push_str(&s2);
    
    • 这样可以避免多次重新分配内存,提高内存使用效率。