0

Please first take a look at the code below.

struct Point<T> {
    x: T,
}

impl<T> Point<T> {
    fn get_x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let p = Point { x: 5 }; // Point<i32>

    let x_value = p.get_x(); // &i32

    println!("{}", x_value);
}

This code prints 5 and nothing seems surprising, but I was wondering why the type of x_value has an & in front of i32. It seems redundant and if I change the line of println!("{}", x_value); to println!("{}", *x_value);, it also successfully prints 5. My question is, is there a preferred way when we have an option to return either referenced or dereferenced value?

I also would like you to check the following code.

struct Point<T> {
    x: T,
}

impl<T> Point<T> {
    fn get_x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let p = Point { x: "hello" }; // Point<&str>

    let x_value = p.get_x(); // &&str

    println!("{}", x_value);
}

The code is the same as the first one except the type of x_value is now &&str and it prints hello. I can dereference x_value and the type of x_value becomes &str, and it also prints hello. Same question. Should I care about dereferencing x_value and get &str instead of getting &&str? Is there a performance gain or some kind of benefit for choosing over the other one?

tet
  • 1,287
  • 1
  • 17
  • 36
  • I think [this answer](https://stackoverflow.com/questions/27852613/why-does-printing-a-pointer-print-the-same-thing-as-printing-the-dereferenced-po) your question. – Abdul Niyas P M Sep 30 '21 at 11:19
  • 2
    You are maybe confused, because you are only dealing with types that are [cloneable](https://doc.rust-lang.org/std/clone/trait.Clone.html). Create a struct (`struct Foo`), insert into your `Point` struct and call `get_x`. Observe what happens if you remove the `&` in front of `&self.x`. Does that help you? – hellow Sep 30 '21 at 11:26
  • It's not just that the type is cloneable, even with a non-cloneable the specific example would work because `println!` will automatically reference the object it's given, so `println!("{}", *foo)` is desugared to `Arguments { &*foo }`, and thus still a reference. You'd need an intermediate step to force the move e.g. `{*foo}` would do the trick. However it would break as soon as something less magic is used. – Masklinn Sep 30 '21 at 11:41
  • Thank you for all the comments, but I'm still bit confused. If I understand correctly, I can add `&` as many as I want to any cloneable type even though it is unnecessary. So, let's say I add `&` to some value and there is no performance degradation even a tiny bit? – tet Sep 30 '21 at 11:50
  • I just think that getting the value of `i32` seems cleaner than `&i32` and if both values produce the same output, should I dereference `&i32` and get `i32` value or it doesn't matter? – tet Sep 30 '21 at 12:11
  • "Add `&` to some value" sounds too arbitrary. Do you need the value or the _reference_ to the value? The two are quite different and are associated ith different tradeoffs. Getting the value requires type to be `Copy` or `Clone`. Getting the reference carries no such requirement, but will prevent you from modifying or dropping the value while any reference is alive. A rule of thumb is that it's more efficient to get the value if its size is <= size of pointer. Also, keep in mind that Rust optimizes aggressively, so in many situations either variant will compile to the same machine code. – user4815162342 Sep 30 '21 at 12:51
  • @user4815162342 `Do you need the value or the reference to the value?` This is the question I'm trying to solve. I can choose to have the value or the reference to the value because they both produce the same output. So, I was wondering if choosing one over the other one has some kind of benefit. `keep in mind that Rust optimizes aggressively, so in many situations either variant will compile to the same machine code` This phrase might be the answer I was looking for. I guess it doesn't matter if I get the value of type `i32` or `&i32` or `&&&&i32` when it compiles and gives the same output. – tet Sep 30 '21 at 22:16

0 Answers0