What's the difference between reference vs slice?

let s = String::from("hello world");

    let a = &s[..]; //slice
    let b = &s; // reference

Technically both a and b are same right? Both holding a memory address to a value

No. Slicing a string gets you to the underlying buffer. The address of a string, &String can be deref-coerced to a &str that points to the backing buffer, but it isn't the same thing. The address of a string is the address of the string handle itself.

1 Like

Those aren't the same, they have different types: a is &str, b is &String. So there is an extra indirection in the second one.

To give some details on what is going on: the s[..] syntax is applying an indexing using the .. range (which refers to the full range). That indexing goes through the implementation of Index<RangeFull> for String, which outputs &str. The indexing syntax actually inserts a dereference of the return value from index(), so an additional & is needed to make it back into a &str. It consists of a pointer to the start of the string and the length of the string.

The second case is just taking a reference to the String structure, which contains a pointer, length and capacity. The resulting &String type is thus represented by a simple pointer (with the length behind it alongside another pointer to the string data).


They hold a reference to a different memory address. a points to the start of your string and b points to the (pointer to string, length, capacity) tuple on the stack. Furthermore a includes the length of the string. It is a so called fat pointer.

Here's a recent post summarizing slices, and another diagraming the difference between &Vec<_> and &[_] (which is the same as the difference between &String and &str).

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.