String在增加内容时,内部要重新分配地址吧?但似乎没有。代码如下:
#![feature(vec_into_raw_parts)]
fn main() {
let s = String::from("hello");
unsafe {
let (ptr, len, cap) = s.into_raw_parts();
println!("{:p},{},{}", ptr, len, cap);
let x = Box::new(3); //干扰一下地址分配,免得后面的内存申请重用旧地址
println!("{}", x);
let mut s = String::from_raw_parts(ptr, len, cap);
let y = Box::new(4); //再次干扰
println!("{}", y);
s.push_str(" world"); //应该新分配内存了吧
let (ptr, len, cap) = s.into_raw_parts();
println!("{:p},{},{}", ptr, len, cap); //但没有,为什么?
}
}
是在playground上用nightly测试的。
Ext Link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=b3b941499de85c6a77161a7f10553381
1
共 7 条评论, 1 页
评论区
写评论肯定一些情况会重分配呀
这么写大概率地址不一样。
应该是重新分配空间时有优化,后面有连续空间可利用时就直接扩容。若干扰数据太多,原空间旁边的未分配空间不够用时才全部搬新家。
我用bumpalo测试,地址是改变了的。
也有可能是追加的数据太少了。
初次分配可能会分配一部分内存,然后,追加的长度还够用的情况下不需要重新分配。
我刚才测试,追加很长的字符串,地址发生了变化。
我学习一下grow,感谢,祝国庆快乐!
👇
johnmave126:...
std用的allocator trait是
alloc::alloc::Allocator
,其中支持grow
,String在增加长度的时候会call grow,而allocator决定具体怎么grow。这跟libc里面的malloc/free/realloc很像,allocator在条件允许的情况下是可以直接把之前分配的内存块加长而不改变其位置的。改成以下代码也是一样的结果: