Hello,
I just discovered that I can easily log in with GitHub account, so I might ask a simple question now.
I just started reading the official Rust book. I initially intended to learn some Rust already in 2014, but them spent nine years with Nim instead.
I read the first five chapters of the Rust book a few days ago, and most seems to be well explained. But still there are some difficult points, e.g. ownership transfer of plain stack allocated data. (I think I understand it for data with heap allocated components as for the String data type mostly used in the fine explanations.) In chapter What is Ownership? - The Rust Programming Language we have
Stack-Only Data: Copy
There’s another wrinkle we haven’t talked about yet. This code using integers—part of which was shown in Listing 4-2—works and is valid:
let x = 5; let y = x; println!("x = {}, y = {}", x, y);
But this code seems to contradict what we just learned: we don’t have a call to
clone
, butx
is still valid and wasn’t moved intoy
.The reason is that types such as integers that have a known size at compile time are stored entirely on the stack, so copies of the actual values are quick to make. That means there’s no reason we would want to prevent
x
from being valid after we create the variabley
. In other words, there’s no difference between deep and shallow copying here, so callingclone
wouldn’t do anything different from the usual shallow copying, and we can leave it out.
Well, so for plain stack allocated data like integers there is no reason for a move, as a copy is very fast. But what is for (stack allocated) arrays or structs containing only plain types like integers? The explanations are not fully clear, so my guess was that there is no move and borrow for pure stack allocated data.
But them, in chapter An Example Program Using Structs - The Rust Programming Language the book told us:
Here’s an example where we’re interested in the value that gets assigned to the
width
field, as well as the value of the whole struct inrect1
:#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let scale = 2; let rect1 = Rectangle { width: dbg!(30 * scale), height: 50, }; dbg!(&rect1); }
We can put
dbg!
around the expression30 * scale
and, becausedbg!
returns ownership of the expression’s value, thewidth
field will get the same value as if we didn’t have thedbg!
call there. We don’t wantdbg!
to take ownership ofrect1
, so we use a reference torect1
in the next call. Here’s what the output of this example looks like:
“We don’t want dbg!
to take ownership of rect1
, so we use a reference to rect1
in the next call.”
So in principle, a function can take ownership for pure stack allocated data like this Rectangle struct? Which we avoid here by use of the reference? Note that there is never a dealloc() operation for stack allocated data. My guess would be, that in this case, the reference is used to avoid the copy effort, like using pointers in C, and not because of ownership transfer? But I am not sure.
Well, I might finally understand this when continuing reading the book or thinking about it more, but asking might be OK as well, as most Rust people seems to be smart and friendly.
Best regards,
Stefan Salewski