一旦其所有者超出范围,谁是串联字符串的所有者?

Bog*_*Pop 5 string ownership rust

我正在学习 Rust,Rust 编程语言书的第 8.2 章提出了一些疑问:

let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
println!("s2 is {}", s2);
Run Code Online (Sandbox Code Playgroud)

如果该push_str方法获得了 的所有权s2,我们将无法在最后一行打印其值。

我理解这一点以及连接仅添加对字符串的引用而没有获得其所有权的事实。这应该意味着如果s2超出范围或被更改,连接的字符串应该被释放或更改,但它不会发生:

let mut s1 = String::from("foo");
{
    let mut s2 = String::from("bar");
    s1.push_str(&s2[..]);
    println!("s2 is {}", s2);

    println!("s1 is {}", s1);
    s2 = String::from("lol");

    println!("s2 is {}", s2);
}
println!("Value after change is {}", s1);
Run Code Online (Sandbox Code Playgroud)

由于连接后的字符串只是对字符串的引用s2s1并没有获得字符串的所有权,一旦s2超出范围,连接后的字符串的所有者是谁?

Cor*_*ien 12

Stringstr存储为 UTF-8 字节的连续数组。

String "foo"                         &str "bar"
[ len: 3 | data:? ]                  [ len: 3 | data:? ]
                ?                                    ?
                v                                    v
                [ f | o | o ]   [ more memory... ]   [ b | a | r ]
Run Code Online (Sandbox Code Playgroud)

当你这样做时s1.push_str(&s2[..]), 的字节s2被复制到所拥有的内存的末尾s1(可能重新分配以腾出更多空间),保持s2原样。

              ??????????????????????
              v                    ?
[ f | o | o | b | a | r ]        [ b | a | r ]
Run Code Online (Sandbox Code Playgroud)

底层字节必须是连续的这一事实意味着无法使用 Rust 的String/&str类型执行非复制追加操作。这样的操作需要将字符串类型实现为例如字符串块的链表而不是单个连续数组。

  • “*字符串块的链接列表*”...或 `Vec<&str>`。 (2认同)