Rust内存管理基础疑问求助:地址与生命周期相关问题
Rust内存管理常见问题解答
问题1:遮蔽Vec后,切片引用地址与新Vec地址为何不同?
代码示例:
fn get_pointer(vec: &[i32]) -> &[i32] { vec } fn main() { let vector = vec![1, 2, 3, 4, 5]; let first_element = get_pointer(&vector); let vector: Vec<String> = Vec::new(); println!( "Vector: {:p}, and func result: {:p}", &vector, first_element ); }
输出:Vector: 0x5181aff7e8, and func result: 0x17e5bad99b0
解答
&vector打印的是栈上Vec结构体自身的内存地址,遮蔽后的vector是栈上的全新变量,地址自然是新的。first_element是指向堆上Vec元素数组的切片引用,它保存的是堆中元素起始位置的地址,和栈上的Vec结构体地址完全不是一回事,所以两者地址必然不同。
问题2:打印的"元素地址"与"引用变量地址"为何不同?
代码示例:
fn get_pointer_to_first_element(vec: &[i32]) -> &i32 { &vec[0] } fn main() { let vector = vec![1, 2, 3, 4, 5]; let first_element = get_pointer_to_first_element(&vector); println!( "from variable: {:p}, from function: {:p}", &vector[0], &first_element ); }
输出:from variable: 0x1f9a887da80, from function: 0x15fe2ffb10
解答
&vector[0]取的是堆上Vec第一个元素的实际内存地址,也就是元素值1所在的位置。&first_element取的是栈上引用变量first_element自身的地址——这个变量是用来存储堆上元素地址的容器,它自己在栈上有独立的位置。
两者指向的是完全不同的内存区域,所以地址必然不同。
问题3:函数内的引用变量销毁后,外部为何还能使用?遮蔽变量后原变量会被销毁吗?
代码示例:
fn get_pointer_to_first_element(vec: &[i32]) -> &i32 { let pointer = &vec[0]; pointer } // 此处变量"pointer"及其值应被销毁,为何外部仍可使用? fn main() { let vector = vec![1, 2, 3, 4, 5]; let first_element = get_pointer_to_first_element(&vector); let vector: Vec<String> = Vec::new(); // 疑问:原vector是否会被销毁? println!("first element is available and its {first_element}. "); }
输出:first element is available and its 1.
解答
函数内引用变量销毁后外部仍可使用的原因:
函数里的pointer是栈上的引用变量,它的作用是存储堆上元素的地址。当函数返回pointer时,返回的是它存储的堆元素地址,而不是pointer这个栈变量本身。只要原Vec的堆元素还存活,这个地址对应的内容就有效。pointer作为栈变量在函数结束后会被销毁,但它指向的堆元素不受影响。遮蔽变量后原变量的生命周期:
虽然你用新的vector: Vec<String>遮蔽了原vector: Vec<i32>,但原Vec并没有立即被销毁——因为first_element持有原Vec的引用,Rust的借用检查器会强制原Vec的生命周期延长到first_element不再被使用的时候。如果没有这个引用,遮蔽后原变量会被立即销毁并释放堆内存。
内容的提问来源于stack exchange,提问作者NekkiNekkiNekki
相关产品推荐
相关产品推荐

