Watch 25 Star 65 Fork 17

hainuo / rust ebookRuby

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
Clone or download 10.62 KB
Copy Edit Web IDE Raw Blame History
hainuo authored 2015-07-08 22:38 . 语法变量引用

% Ownership 所有权

This guide is one of three presenting Rust’s ownership system. This is one of Rust’s most unique and compelling features, with which Rust developers should become quite acquainted. Ownership is how Rust achieves its largest goal, memory safety. There are a few distinct concepts, each with its own chapter:


  • ownership, which you’re reading now 所有权系统 你正在阅读的章节
  • borrowing, and their associated feature ‘references’ 借用 它们相关特性的‘引用’
  • lifetimes, an advanced concept of borrowing 生命周期 借用的一个高级概念

These three chapters are related, and in order. You’ll need all three to fully understand the ownership system.


Meta 元

Before we get to the details, two important notes about the ownership system.


Rust has a focus on safety and speed. It accomplishes these goals through many ‘zero-cost abstractions’, which means that in Rust, abstractions cost as little as possible in order to make them work. The ownership system is a prime example of a zero-cost abstraction. All of the analysis we’ll talk about in this guide is done at compile time. You do not pay any run-time cost for any of these features.

Rust注重安全和速度。它通过许多‘0成本抽象’来达成目标,这意味着在Rust中,抽象花费尽可能少的代价来使他们工作。所有权体系是0成本抽象的一个最佳实践。在本指引中我们要谈论的所有的分析是在 编译时内完成 的。你不需要为这些特性花费任何运行时。

However, this system does have a certain cost: learning curve. Many new users to Rust experience something we like to call ‘fighting with the borrow checker’, where the Rust compiler refuses to compile a program that the author thinks is valid. This often happens because the programmer’s mental model of how ownership should work doesn’t match the actual rules that Rust implements.You probably will experience similar things at first. There is good news, however: more experienced Rust developers report that once they work with the rules of the ownership system for a period of time, they fight the borrow checker less and less.


With that in mind, let’s learn about ownership.


Ownership 所有权

Variable bindings have a property in Rust: they ‘have ownership’ of what they’re bound to. This means that when a binding goes out of scope, the resource that they’re bound to are freed. For example:


fn foo() {
    let v = vec![1, 2, 3];

When v comes into scope, a new Vec<T> is created. In this case, the vector also allocates space on the heap, for the three elements. When v goes out of scope at the end of foo(), Rust will clean up everything related to the vector, even the heap-allocated memory. This happens deterministically, at the end of the scope.


Move semantics 移动语义

There’s some more subtlety here, though: Rust ensures that there is exactly one binding to any given resource. For example, if we have a vector, we can assign it to another binding:


let v = vec![1, 2, 3];

let v2 = v;

But, if we try to use v afterwards, we get an error:


let v = vec![1, 2, 3];

let v2 = v;

println!("v[0] is: {}", v[0]);

It looks like this:


error: use of moved value: `v`
println!("v[0] is: {}", v[0]);

A similar thing happens if we define a function which takes ownership, and try to use something after we’ve passed it as an argument:


fn take(v: Vec<i32>) {
    // what happens here isn’t important.

let v = vec![1, 2, 3];


println!("v[0] is: {}", v[0]);

Same error: ‘use of moved value’. When we transfer ownership to something else, we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of special annotation here, it’s the default thing that Rust does.


The details 细节

The reason that we cannot use a binding after we’ve moved it is subtle, but important. When we write code like this:


let v = vec![1, 2, 3];

let v2 = v;

The first line allocates memory for the vector object, v, and for the data it contains. The vector object is stored on the stack and contains a pointer to the content ([1, 2, 3]) stored on the heap. When we move v to v2, it creates a copy of that pointer, for v2. Which means that there would be two pointers to the content of the vector on the heap. It would violate Rust’s safety guarantees by introducing a data race. Therefore, Rust forbids using v after we’ve done the move.


It’s also important to note that optimizations may remove the actual copy of the bytes on the stack, depending on circumstances. So it may not be as inefficient as it initially seems.


Copy types Copy类型

We’ve established that when ownership is transferred to another binding, you cannot use the original binding. However, there’s a trait that changes this behavior, and it’s called Copy. We haven’t discussed traits yet, but for now, you can think of them as an annotation to a particular type that adds extra behavior. For example:


let v = 1;

let v2 = v;

println!("v is: {}", v);

In this case, v is an i32, which implements the Copy trait. This means that, just like a move, when we assign v to v2, a copy of the data is made.But, unlike a move, we can still use v afterward. This is because an i32 has no pointers to data somewhere else, copying it is a full copy.


We will discuss how to make your own types Copy in the traits section.


More than ownership 不只是所有权

Of course, if we had to hand ownership back with every function we wrote:


fn foo(v: Vec<i32>) -> Vec<i32> {
    // do stuff with v

    // hand back ownership

This would get very tedious. It gets worse the more things we want to take ownership of:


fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
    // do stuff with v1 and v2

    // hand back ownership, and the result of our function
    (v1, v2, 42)

let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];

let (v1, v2, answer) = foo(v1, v2);

Ugh! The return type, return line, and calling the function gets way more complicated.


Luckily, Rust offers a feature, borrowing, which helps us solve this problem.It’s the topic of the next section!


Comment ( 0 )

Sign in for post a comment