rust Ownership,Reference and Lifetime

1. Ownership

rust的ownership系统是它区别与其它语言的最主要的特征。只有理解了ownership系统,才能真正算是入门。

Rust的绑定变量有一个属性:获得它所绑定资源的所有权。这意味着当绑定变量超出作用域时,它所绑定资源的资源就会释放。

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">foo</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

绑定变量v的作用域是函数foo的函数体,创建v时,先会在栈上分配空间来保存v这个变量 ,然后会在堆上分配空间以保存它的3个元素。当v超出作用域时,Rust会清除栈和堆上这些资源。

有一点要注意:Rust确保有且只有一个变量绑定到给定的资源

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建一个vector,并绑定到一个变量</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v2 = v;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把它赋给另一个变量。</span>

println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"v[0] is: {}"</span>, v[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]);   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//使用原来的那个绑定变量。</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

运行上面的代码会报错。

<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">error</span>: <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">use</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">of</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">moved</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">value</span>: `<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">v</span>`
<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">println</span>!("<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">v</span><span class="hljs-attr_selector" style="color: rgb(0, 136, 0); box-sizing: border-box;">[0]</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">is</span>: <span class="hljs-rules" style="box-sizing: border-box;">{<span class="hljs-rule" style="box-sizing: border-box;">}</span></span>", <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">v</span><span class="hljs-attr_selector" style="color: rgb(0, 136, 0); box-sizing: border-box;">[0]</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">let</span> v2= v;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这行代码是把v赋给v2,它们都指向同一个vector,这违反了Rust安全承诺。所以在这个赋值后Rust不允许再使用变量v。在编译器优化时,可以会把它释放掉。看起来就像v的所有都转移(move)到v2了。

下面我们再看一个例子,这回我们把类型从vector换成i32.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v  = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v2 = v;

println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"v is: {}"</span>, v);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

这个代码就可以运行,为什么?因为这个例子里v的类型是i32,它实现了Copy trait,所以let v2 = v;这行代码执行时,rust会把v的值深度copy一份,然后给v2,所以v在赋值后可以用的。 
v2和v拥有不同的资源,分别是各自资源的owner。

move还是copy ?

当一个局部变量用做右值时,它可能会被move或copy,取决于它的类型,如果它实现了Copy这个trait,那它就会被copied,否则就会被moved.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v2 = v;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

vector没有实现Copy trait,所以在赋值后v就不可以用了。

如果我们写了一个函数,以vector为参数,为了能让函数调用后原来的变量能正常使用,我们必须手动归还这个ownership。

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">foo</span>(</span>v1: Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>, v2: Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>) -> (Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>, Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>) {
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// do stuff with v1 and v2</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// hand back ownership, and the result of our function</span>
    (v1, v2, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">42</span>)
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> (v1, v2, answer) = foo(v1, v2); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调用并归还</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

这简直太变态,无法接受啊!

所以rust引入了borrowing 来解决这个问题。

2. References and Borrowing

在Ownership一节,我们给出了一个手动归还Ownership例子,手动归还实在太不方便。

Rust使用reference 来解决这个问题。这是reference版本的。

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">foo</span>(</span>v1: &Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>, v2: &Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>) -> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span> {
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// do stuff with v1 and v2</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// return the answer</span>
    <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">42</span>
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> answer = foo(&v1, &v2);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// we can use v1 and v2 here!</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

reference是什么?官方文档是这样解释的。

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">We call <span class="hljs-operator" style="box-sizing: border-box;">the</span> &T type <span class="hljs-operator" style="box-sizing: border-box;">a</span> ‘reference’, <span class="hljs-operator" style="box-sizing: border-box;">and</span> rather than owning <span class="hljs-operator" style="box-sizing: border-box;">the</span> resource, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> borrows ownership.</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

borrow,借,也就是所有权是没变的。我借你的书看,书还是你的(所有权归你),但是我现在在用它。 
引用也是这个意思,引用可以使用资源,但是不拥有所有权。

默认的References不可变的,跟绑定一样.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">foo</span>(</span>v: &Vec<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>) {
     v.push(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> v = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">vec</span>![];

foo(&v);
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

会报错:

<code class="hljs fsharp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">error: cannot borrow immutable borrowed content `*v` <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mutable</span>
v.push(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);
^</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

不可变的引用,不能修改资源的内容。如果要修改资源的内容,我们先取得可变引用

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> x = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> y = &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> x;
    *y += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
}
println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span>, x);
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

x的值被修改了。你会奇怪,我们为什么要把修改的代码放在{}块里。如果我们把这两个花括号去掉会报错。

<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">error</span>: cannot borrow `x` <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> immutable because <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> also borrowed <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> mutable
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span>, x);
                   ^
note: previous borrow <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> `x` occurs here; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> mutable borrow prevents
subsequent moves, borrows, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> modification <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> `x` <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">until</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> borrow ends
        let y = &mut x;
                     ^
note: previous borrow ends here
fn main() {

}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

为什么? 
我们先来说说Rust对references规定吧。

  1. 所有的引用的作用域必须小于所有者(owner)的作用域。
  2. 你可以有多个不可变的引用(&T),但
  3. 同时只能有一个可变的引用(&mut T)

我们再来看上边的例子:

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> x = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> y = &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> x;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// -+ 可变引用 y 开始生效</span>
                   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |</span>
*y += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;           <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |</span>
                   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |</span>
println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span>, x); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// -+ - 试图使用原来的可变绑定</span>
                   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// -+ 可变引用 y 离开作用域</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

我们无法在可变引用y的作用域里使用x. 因为它违反了同时只能有一个可变引用的这条规则。

了解了引用我们下面再来学习Liftetime.

3. Lifetime

Lifetime是刚接触rust时特别容易产生迷惑的一个概念,所以我在这里花了比较大的篇章来说明它,基于我自己的理解,希望能给大家讲明白。

在上一节里我们讲了引用和借用 
把资源的引用借给他人使用其结果可能会很复杂。假如:

  1. 我有一个资源
  2. 我把这个资源的引用借给你
  3. 我释放这个资源(我不关心你那儿还有一个引用,因为我是这个资源的owner,我有权释放它)。然后
  4. 你要使用这个引用。

第4步,当你使用引用时,它所指向的资源已经不在了!这将导致不可预知的问题。

如何避免上述情况的发生?

一种解决方案就是: 当还有一个指向资源的引用存在时,资源就不能被释放。 没有指向资源的引用时,才能释放它。

这个方案下第3步就不会释放资源,第4步就是安全的。

在这种情况下资源怎么释放呢?有两种方案,引用计数(ARC)和垃圾回收器GC. Objective-C和Swift使用的是ARC,java和.net使用的是GC.

rust没有使用ARC也没有使用GC. onwer使用完了资源(通常是owner超出作用范围自动销毁)就会释放资源。

那第4步怎么办?

Rust使用某种机制来保证第4步不会发生!

你会说怎么不会发生? 我代码就要这样写,那当然会发生啊,比如:

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f:Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> y : &Foo;

    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> x = Foo{f : Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>)};   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这相当于第1步,获得资源。</span>

        y = &x;                              <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这相当于第2步, 借出 reference.</span>
    }                                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这相当于第3步 onwer超出作用范围,释放资源</span>

    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span>,y.f);                      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这相当于第4步。 通过reference来使用资源。</span>

}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

好像第4步发生了呀。 不好意思,这段代码无法成功编译。Rust compiler会检查引用的lifetime和 
owner的lifetime。它发现引用的生命期比资源的owner的长时,它编译时就报错了,根本就不会到 
运行这一步。所以第4步是不会发生的。

因此在Rust里,你必须在owner释放资源之前使用它(借出)的引用。就也是上述的第4步应该发生在第3步之前。

1 我有一个资源

2 我把这个资源的引用借给你

4 你使用这个引用。

3 我释放这个资源。

上述的代码如果用java或swift来实现肯定可以编译通过。 我们已经习惯写这样的代码了,我们理所当然 
地认为这样的代码可以运行。但是在rust里,你不能这样写代码,因为rust不允许你这样写。

如何保证第4步发生在第3步之前呢?rust是通过保证资源owner活得比它的任何一个引用更长来实现的。

Rust通过叫lifetime的概念来实现。

下面我们举些例子来说明lifetime。在这之前,请记住:有引用才有lifetime,lifetime是跟引用关联的.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Bar {
    foo : &Foo,  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//struct包含引用,就必须明确指定lifetime.</span>
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> a = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>)};

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> y : &Foo;

    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> x = &a;
        y = x;
    }
    a.f = Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span> ,  a.f);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li></ul>

上面的代码会在第2个struct: Bar 处报错error: missing lifetime specifier。而第1个struct Foo就不报错这个错误,因为它没有用包含引用。

好,我们现在给它加上lifetime。

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Bar<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a> {
    foo : &'</span>a Foo
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> a = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>)};

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> y : &Foo;

    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> x = &a;
        y = x;
    }
    a.f = Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span> ,  a.f);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li></ul>

OK,可以编译通过了。

很多人会被Bar<'a>foo : &'a Foo里面的'a搞懵了,不明白它是干什么的,它如何起作用.

'a 是Named lifetime,中文可译为带名生命期。它实际上是告诉编译器,struct Bar有引用,这个引用的lifetime我们把它命名为:a.

做为开发人员我们不用关心'a是怎么生效的。因为我们不会直接用到它。开发人员要就做的就是给引用加上一个带名生命期。然后由编译器来使用它。

当我们的struct包含了一个引用,那我们struct的实例不能比它包含的引用活得更长

如果不能理解这句话,请翻到前面看开头的那个4步的说明.

那什么是lifetime ? lifetime是rust用来度量引用生命期的一个辅助标识。编译器用它来计算引用的寿命有多长。 很多人认为lifetime这个词选择不太好,容易产生误解[1]。

'a这种东西只是用来计算生命期的标识,好理解了吧?

下面我们看一个struct包含多个引用时的情况,这时带名生命期的作用就更容易理解。

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Bar<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a,'</span>b> {
    foo : &<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a Foo,
    doo : &'</span>b Foo
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> a = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>)};

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> d : &Foo;

    { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// block1</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> b = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>)};

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> bar = Bar{ foo : &a,doo : &b};
        println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span> ,  bar.foo.f);

        d = bar.foo;
    } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// end of block1</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//a.f = Box::new(1);</span>
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span> ,  d.f);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

首先如果一个struct有多个引用,那它的实例的寿命只能和最短命的那个引用一样长。 a的寿命是整个main函数,而b的寿命是block1, 
所以bar的寿命只能是block1。

如果我们把block1的最后一行改成:

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">d = bar.doo;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

就会无法编译:

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Bar<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a,'</span>b> {
    foo : &<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a Foo,
    doo : &'</span>b Foo
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> a = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>)};

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> d : &Foo;

    { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// block1</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">mut</span> b = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>)};

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span> bar = Bar{ foo : &a,doo : &b};
        println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span> ,  bar.foo.f);

        d = bar.doo;
    } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// end of block1</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//a.f = Box::new(1);</span>
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"{}"</span> ,  d.f);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

好,接下来我们看看lifetime和函数的关系。

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">test</span>(</span>a : &Foo,b : &Foo) -> &Foo {
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a : {} - b : {}"</span>,a.f,b.f);
    b;
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span>  a = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>)};


    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span>  b = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>)};
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//println!("{}" ,  bar.foo.f);</span>
    test(&a,&b);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

函数test有两个类型为&Foo,无需为这个函数显式指定lifetime。如果函数返回一个引用,则必须为函数显式指定lifetime。

我们修改代码,让函数返回一个引用,我们先不给它加lifetime,看看编译器提示什么.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">test</span>(</span>a : &Foo,b : &Foo) -> &Foo {
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a : {} - b : {}"</span>,a.f,b.f);
    b;
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span>  a = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>)};


    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">let</span>  b = Foo {f: Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>)};
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//println!("{}" ,  bar.foo.f);</span>
    test(&a,&b);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>
<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><anon>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">31</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">error</span>: missing lifetime specifier [E0106]
<anon>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span> fn test(a : &Foo,b : &Foo) -> &Foo {
                                       ^~~~
<anon>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">31</span>: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span> help: this function's <span class="hljs-constant" style="box-sizing: border-box;">return</span> type <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">contains</span> a borrowed value, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">but</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> signature <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">does</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> <span class="hljs-command" style="box-sizing: border-box;">say</span> whether <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> borrowed <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> `a` <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> `b`
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">error</span>: aborting due <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> previous <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">error</span>
playpen: <span class="hljs-type" style="box-sizing: border-box;">application</span> terminated <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">error</span> code <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">101</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

我们的函数返回了一个引用,px 有两引用类参数,编译器不知道返回的引用是从哪个参数借来的.所以时我们必须显式指定lifetime.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">test</span><</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a> (a : &Foo,b : &'</span>a Foo) -> &<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a Foo {
    println!("a : {} - b : {}",a.f,b.f);
    b
}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

可不可以返回值的lifetime与参数的不相关呢?

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">test</span><</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a,'</span>b> (a : &Foo,b : &<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a Foo) -> &'</span>b Foo ;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

上面的函数可能实现吗?如何从函数里面返回一个带新的lifetime的引用?在函数里新创建一个Foo?这样它就有了一个新的lifetime? 
问题是函数体内创建的实例会在函数返回时销毁,引用就会失效.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">test</span><</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a,'</span>b> (a : &Foo,b : &<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a Foo) -> &'</span>b Foo {
    println!(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"a : {} - b : {}"</span>,a.f,b.f);
    &Foo{f : Box::new(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>)}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

可以看出来函数返回值的lifetime一定是跟某个参数的一致的

函数返回一个引用时必须显示指定lifetime,因为这个返回的引用延长了引用生命期.

没有返回值的函数也能延长引用的生命期.

<code class="language-rust hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Foo {
    f : Box<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">i32</span>>,
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Link<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a> {
    link: &'</span>a Foo,
}

<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">fn</span> <span class="hljs-title" style="box-sizing: border-box;">store_foo</span><</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a> (x: &mut Link<'</span>a>, y: &<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'a Foo) {
    x.link = y;
}

fn main() {
    let a = Foo{f : Box::new(1)};

    let x = &mut Link{ link : &a };

    if false {
        let b = Foo { f: Box::new(2) };

        store_foo(x, &b);  //在这里试图延长b的引用的生命期,但是b会在if块后销毁,&b就会成为野引用,所以这行代码无法编译.
    }
}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

Rust的Borrow和Lifetime虽然有一点难理解,但请相信,一旦弄懂并开始coding,你会爱上它,:D。

你可能感兴趣的:(rust Ownership,Reference and Lifetime)