Im struggling to fully grasp what happens to the memory part during ownership transfer. if a value is owned by one variable and transferred to another, what happens to the memory in the original variable's stack frame after the transfer
As an example, t is out of scope, but test still works. Where is Test(1) stored, and how is it still valid after the block ends if its created in the stack?
struct Test(u8);
impl Drop for Test {
fn drop(&mut self) {
println!("{} is dropped", self.0);
}
}
fn main() {
let test;
{
println!("step 1");
let t = Test(1);
println!("step 2");
test = t;
}
println!("{}", test.0);
}
output:
step 1
step 2
1
1 is dropped
When an owner goes out of scope, Rust automatically clean-up the data associated with that owner by reclaiming memory. Here's an example that seems to contradict it:
fn main() {
println!("step 1");
let test = create_struct();
println!("step 2");
println!("{}", test.0);
}
pub fn create_struct() -> Test {
Test(1)
}
output:
step 1
step 2
1
1 is dropped
If memory is reclaimed when an owner goes out of scope, how does returning a value from a function prevent this?
Judging from the output of the first example, it's not copied because only one instance of Test was dropped, also that means the stack memory wasn't reclaimed in the inner block or what is happening here?
Disclaimer: what actually happens in memory is difficult to pinpoint due to optimizations. For example, a variable doesn't need to be stored in memory at all, it could be in a CPU register. The remainder of this answer assumes that the variables are stored in memory in the "obvious" way.
if a value is owned by one variable and transferred to another, what happens to the memory in the original variable's stack frame after the transfer
It remains unused (or gets reused for storing other variables, with optimization).
As an example, t is out of scope, but test still works. Where is Test(1) stored, and how is it still valid after the block ends if its created in the stack?
It is first stored in t
, then moved (bitwise-copied) to test
. After the move, the memory in t
is no longer relevant.
If memory is reclaimed when an owner goes out of scope, how does returning a value from a function prevent this?
It prevents this by moving the value to another location. If you just called create_struct();
without assigning the value to anything, it would indeed get dropped. By assigning it to a variable, you effectively extend its life.
Judging from the output of the first example, it's not copied because only one instance of Test was dropped
That's correct - it wasn't copied, it was moved. Unlike C++, Rust doesn't do implicit copies, you have to call .clone()
explicitly, and then that value is moved.
also that means the stack memory wasn't reclaimed in the inner block or what is happening here?
The stack memory gets reclaimed once the function returns. Before that, moving or dropping the value doesn't reclaim the memory due to how stack works.