Pointers 为什么指针的地址不';在Rust中修改字符串变量时是否更改?

Pointers 为什么指针的地址不';在Rust中修改字符串变量时是否更改?,pointers,memory,rust,Pointers,Memory,Rust,我认为rust在修改字符串时会在堆内存中生成另一个数据。因此,当我将一个值推送到字符串变量时,我希望指针地址会改变 fn main(){ 让mut hello=String::from(“hello”); println!(“{:?}”,hello.as_ptr());//0x7fcfa7c01be0 你好,普什街(“世界!”); println!(“{:?}”,hello.as_ptr());//0x7fcfa7c01be0 } 然而,结果表明并非如此。指针的地址没有改变,所以我用vecto

我认为rust在修改字符串时会在堆内存中生成另一个数据。因此,当我将一个值推送到字符串变量时,我希望指针地址会改变

fn main(){
让mut hello=String::from(“hello”);
println!(“{:?}”,hello.as_ptr());//0x7fcfa7c01be0
你好,普什街(“世界!”);
println!(“{:?}”,hello.as_ptr());//0x7fcfa7c01be0
}
然而,结果表明并非如此。指针的地址没有改变,所以我用vector类型测试了它

fn main(){
让mut number=vec![1,2,3];
println!(“{:?}”,numbers.as_ptr());//0x7ffac4401be0
数字推送(4);
println!(“{:?}”,numbers.as_ptr());//0x7ffac4401ce0
}
向量变量的指针地址在修改时发生了更改。字符串和向量类型的内存有什么区别?

Vec
string
可能会保留额外的空间,以避免在每次推送操作时分配空间。这为推送操作提供了摊销O(1)时间

正好是这样,
vec
macro保证创建一个没有额外空间的向量,而
String::from(&str)
没有这样的保证


有关更多详细信息,请参阅。

字符串类似于
Vec
1,因为它既有A也有A。如果当前分配的容量足够容纳新字符串,则无需重新分配基础缓冲区:

向量的容量是为将来添加到向量上的任何元素分配的空间量。这不能与向量的长度混淆,后者指定向量中实际元素的数量。如果向量的长度超过其容量,其容量将自动增加,但其元素必须重新分配

例如,容量为10且长度为0的向量将是一个空向量,其空间可容纳10个以上的元素将10个或更少的元素推到向量上不会改变其容量或导致重新分配。

但是,即使容量发生变化,指针值也不能保证移动。如果相邻有足够的未分配空间,则系统分配器本身可以在不移动分配的情况下调整分配的大小。这似乎就是代码中发生的事情。如果将容量与指针一起打印,则可以观察到以下行为:

let mut hello = String::from("hello");
for _ in 0..10 {
    println!("({:3}) {:?}", hello.capacity(), hello.as_ptr()); // 0x7fcfa7c01be0
    hello.push_str(", world!");
}
(5)0x557624d8da40
(13)0x557624d8da40
(26)0x557624d8dba0
(52)0x557624d8dba0
(52)0x557624d8dba0
(52)0x557624d8dba0
(104)0x557624d8dba0
(104)0x557624d8dba0
(104)0x557624d8dba0
(104)0x557624d8dba0
在本例中,缓冲区大小调整了4次,但内容只移动了一次



实际上,
字符串
是一个新类型的
Vec
,这解释了它们为什么工作相同。

如果有足够的空间,为什么应该这样做?基本测试会给你答案