Rust中&运算符是否同C++仅表取地址?指针与引用地址疑问
Rust中的&运算符和C++不一样!附常见疑问解答
先给结论:Rust的&和C++的&完全不是一回事,它不只是“取地址”,得结合Rust的所有权、引用模型才能搞明白。
先看你贴的代码:
fn main() { //! First question // C++: string* ptr1 = new string("hello"); // so ptr1 contains the address of string "hello" that is allocated on heap let ptr1 = String::from("Hello"); // output: 0x66c96ff910 println!("{:p}", &ptr1); // C++: ptr2 = ptr1 // so they should have now the same address let ptr2 = ptr1; // output: 0x66c96ff910 println!("{:p}", &ptr2); // why ptr1 and ptr2 have different value ? (address of string on heap) // Isn't it because they are fat pointers? // Second question let reference1 = String::from("Hello"); // output: 0x44fc6ff5f0 println!("{:p}", &reference1); // C++: reference1 and referenc2 should point to the same address let reference2 = &reference1; // output: 0x44fc6ff650 println!("{:p}", &reference2); // why reference1 and reference2 don't have the same address? }
疑问1:ptr1和ptr2的堆地址为啥不同?是胖指针的锅吗?
- 你搞混了打印的对象:
println!("{:p}", &ptr1)打出来的是栈上String结构体的地址,不是堆上字符的地址!String本身是栈上的结构体,包含三个东西:堆内存指针、字符串长度、容量(这就是胖指针,但和你问的问题没关系)。 - 当你写
let ptr2 = ptr1时,Rust做的是所有权转移:ptr1直接把自己的所有东西(包括堆内存的所有权)转给ptr2,之后ptr1就不能用了。这时候ptr2接管的是原来ptr1指向的堆内存,堆地址其实是一样的,你要是用ptr2.as_ptr()打印,就能看到和之前ptr1.as_ptr()的结果一致。 - 至于你看到的
&ptr1和&ptr2地址相同,是因为栈空间被复用了,ptr1失效后,ptr2占用了它原来的栈位置而已。根本不是胖指针导致的,是你打印错了对象。
疑问2:reference1和reference2的地址为啥不同?
- Rust里的
&reference1创建的是一个引用变量,它自己是存在栈上的,有独立的地址,这个变量里存的是reference1的地址(也就是栈上String结构体的地址)。 - 你打印的
&reference2是这个引用变量本身的栈地址,不是它指向的地址!要是你直接打印reference2(用println!("{:p}", reference2);),结果就会和&reference1完全一致,因为reference2指向的就是reference1。 - 这就是和C引用的核心区别:C的引用是变量的别名,编译器会优化掉它的独立内存;但Rust的引用是实打实的栈上指针变量,有自己的地址,本质就是个指向目标的指针,只是有生命周期安全检查。
内容的提问来源于stack exchange,提问作者Lorenzo Yang
相关产品推荐
相关产品推荐

