Path for a reference to a vec's item?

In this code:

fn main() {
    let a: Vec<i32> = vec![1,2,3];
    let b: &i32 = &a[2];
    println!("{a:?}, {b}");
}

Should I think of b as path number 2 in the image below, or paths number 1a and 1b (although in this case I'm unsure how it directs to 1b unless it remembers the offset, somehow ?

If you want to edit the image maybe this can be forked from the source.

The address stored in b points directly to the heap-stored data, which I believe you mean by path 2, right?

You can print the addresses of references using the p formatter by the way:

fn main() {
    let a: Vec<i32> = vec![1,2,3];
    
    let b: &i32 = &a[2];
    let heap_addr_of_data_of_a: &[i32] = &a;
    let addr_of_a_on_stack: &Vec<i32> = &a;
    
    println!("{addr_of_a_on_stack:p}, {heap_addr_of_data_of_a:p}, {b:p}");
}

Playground.

2 Likes

Neat, thanks, but there are 8 bytes between b and start of data in a?

0x7ffe34f615e8, 0x64ce6f17ab10, 0x64ce6f17ab18

PD: sorry, i thought it was a[1].

from my test this is the same as &a[0], right? It's just handier to me since the type is only &i32 ?

heap_addr_of_data_of_a is a reference to the whole slice on the heap. &a[0] is a reference to the first element of the slice. The latter can only access the first element, the former allows you to inspect all elements of the slice.

1 Like

In the reply you write:

let heap_addr_of_data_a: &[i32] = &a;

Is that considered the most idiomatic way, or should one use &a[..] ?

Both are semantically equivalent. &a is shorter, but &a[..] a bit more expressive. I wouldn't consider one to be more idiomatic than the other, but that's just my opinion.

1 Like

Keep in mind that although it only "actually" stores the address of the item when running (with the usual "behaves as-if it follows the rules" caveats once you enable optimizations), the borrow is still a reborrow of the implicit borrow of the Vec when you constructed it, and therefore it prevents simultaneous mutable references to any other item (or the Vec itself, eg with a push()) as a compile-time check.

I don't understand what you mean, sorry. But if you rephrase or add a simple snippet I may.