如果不了解什么是变量遮蔽,可以看这篇文章:大白话rust系列04 变量遮蔽
请问如下代码的打印结果是什么?
rust
fn main() {
let language = String::from("Rust");
let language_ref = &language;
let language = 10;
println!("language_ref ={},language = {}",language_ref,language);
}
运行结果如下:
rust
language_ref =Rust,language = 10
let language = 10; 是新建一个同名变量 (遮蔽旧的),不是修改旧变量的值 。language_ref 指向的是旧的那个 String 的内存 ,那块内存从头到尾没被动过,所以打印出来还是 "Rust"。变量名可以复用,但每个变量各自对应不同的内存区域。
也就是说
rust
let language = String::from("Rust");
和
rust
let language = 10;
它们的内存地址不是同一个
把它们的地址打印出来看看吧,代码会稍微多一点点
rust
fn main() {
let language = String::from("Rust");
let language_ref = &language;
// 打印第一个 language(String)相关地址
// 1) String 结构体本身(栈上)的地址
let addr1_var = &language as *const String as usize;
// 2) String 底层堆缓冲区("Rust" 实际所在)的地址
let addr1_heap = language.as_ptr() as usize;
// 3) language_ref 指向的地址(应等于 1)
let addr_ref = language_ref as *const String as usize;
println!("第一次 language(String 变量本身,栈上)地址: 0x{:x}", addr1_var);
println!("第一次 language 底层堆缓冲区(\"Rust\")地址: 0x{:x}", addr1_heap);
println!("\nlanguage_ref 指向的地址: 0x{:x}", addr_ref);
let language = 10; // 新变量,遮蔽旧的
let addr2_var = &language as *const i32 as usize;
println!("\n第二次 language(i32 变量本身,栈上)地址: 0x{:x}", addr2_var);
println!("\nlanguage_ref ={},language = {}\n", language_ref, language);
}
运行结果
rust
第一次 language(String 变量本身,栈上)地址: 0xde023cfaa8
第一次 language 底层堆缓冲区("Rust")地址: 0x29ca21ea090
language_ref 指向的地址: 0xde023cfaa8
第二次 language(i32 变量本身,栈上)地址: 0xde023cfb44
language_ref =Rust,language = 10