Transferring ownership

It's possible (and common) to transfer ownership of a value to a different scope. For example, we can do something like this:

{
let main_1 = Point2D {x: 10.0, y: 10.0};
receive_ownership(main_1);
receive_ownership(main_1); // This will cause a compiler error!
}

What is happening is that the main_1 variable is created and initialized under the ownership of the current scope (the value is pushed onto the stack), but then the ownership is transferred to the scope of the block expression that makes up the receive_ownership function's body, when the value is used as a function parameter. The compiler knows that the current scope is no longer responsible for cleaning up the value stored in main_1, because that job now belongs to a different scope.

The bytes that represent the value on the stack are copied to a new location on the stack, within the scope that is receiving ownership. Most data values store some of their information outside of the stack, though, so the bytes that are left behind in the old scope are considered no longer meaningful or safe to use.

If we try to use the value stored in main_1 after it has been moved to a different scope, as we're doing here with the second call to receive_ownership, the compiler will report an error. It's not just using the value as a function parameter that will cause an error, either. Any use of a value that has been moved is an error. It's no longer there to be used.

Ownership can also be transferred in the other direction. This function receives ownership of its parameter, but then returns the parameter (and hence the ownership) back to the block where it was called:

pub fn receive_ownership(point: Point2D) -> Point2D {
println!("Point2D{{x: {}, y: {}}} is now owned by a new scope", point.x, point.y);
return point;
}

That doesn't mean that the original variable (main_1) becomes usable again, but if we assign the return value from the function to a variable, we can continue using that value through the new variable.

Ownership can also be transferred "sideways" by assigning a value to a different variable. We do something like this:

let mut main_4 = main_2;

Here, the value stored in main_2 is moved to main_4. In this basic example, that's not particularly interesting; we've just got a new variable containing the value that the old variable used to contain, and they're both in the same scope anyway. This gets more interesting when we do things like assigning a value to a structure member, especially when the structure has a different lifetime.

Rust's compiler is very careful about ownership, and when it detects a situation where ownership is not properly respected, or even might not be properly respected, it reports an error. The following function will not compile, because it is only valid when the switch parameter is false:

pub fn uncertain_ownership(switch: bool) {
let point = Point2D {x: 3.0, y: 3.0};

if switch {
receive_ownership(point);
}

println!("point is Point2D{{x: {}, y: {}}}", point.x, point.y);
}

When we try to compile the uncertain_ownership function, we get output like this from the compiler:

As far as the compiler is concerned, if we could have moved the value before using it, we don't get to use it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.187.113