Skip to content

Commit

Permalink
update 2024年 04月 08日 星期一 23:48:29 CST
Browse files Browse the repository at this point in the history
  • Loading branch information
ccrysisa committed Apr 9, 2024
1 parent 9bac624 commit c5e3dea
Show file tree
Hide file tree
Showing 255 changed files with 5,459 additions and 4,617 deletions.
88 changes: 87 additions & 1 deletion content/posts/rust/rust-lifetime.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ repost:
<!--more-->

- 整理自 [@这周你想干啥](https://space.bilibili.com/50713701)[教学影片](https://space.bilibili.com/50713701/channel/collectiondetail?sid=1453665)
- 整理自 B 站 UP 主 [@这周你想干啥](https://space.bilibili.com/50713701)[教学影片合集](https://space.bilibili.com/50713701/channel/collectiondetail?sid=1453665)

{{< admonition >}}
学习 John Gjengset 的教学影片 [Subtying and Variance](https://www.youtube.com/watch?v=iVYWDIW71jk) 时发现自己对 Rust 生命周期 (lifetime) 还是不太理解,于是便前来补课 :rofl:
{{< /admonition >}}

## 引用 & 生命周期

Expand All @@ -53,6 +57,87 @@ repost:

{{< image src="/images/rust/rust-lifetime-02.png" >}}

**单线程** 的程序中,通过函数参数传入的引用,无论其生命周期标注,它的生命周期在该函数的函数体范围内都是有效的。因为从 **状态机** 模型来考虑,该函数没有传入的引用的所有权 (因为是通过参数传入的),所以该函数不可能在其函数体范围内某一节点,就结束传入的引用的生命周期。但是在 **多线程** 的程序,上述规则就不一定成立了。

```rs
fn split<'a, 'b>(text: &'a str, delimiter: &'b str) {...}
```

单线程情况下,参数 `text``delimiter` 在函数 `split` 范围内都是有效的。

也因为这个状态机模型,Rust 的生命周期对于参数在函数体内的使用的影响并不大,主要影响的是涉及生命周期的参数或返回值在 **函数调用后的生命周期推导**,下面给出一些技巧:

{{< admonition tip >}}
**最大共同生命周期**: 从引用的当前共同使用开始,直到任一引用对应的 object 消亡,即其生命周期结束。

当以相同的生命周期标注,来对函数参数的生命周期进行标注时,其表示参数的最大共同生命周期,例如:

```rs
fn f<'a>(x: &'a i32, y: &'a i32, z: &'a i32) {...}
```

生命周期 `'a` 表示参数 `x`, `y`, `z` 的最大共同生命周期,即 `x`, `y`, `z` 可以共同存活的最大生命周期。

当以相同的生命周期标注,来对函数参数和返回值的生命周期进行标注时,其表示返回值的生命周期必须在参数的生命周期内,例如:

```rs
fn f<'a>(x: &'a i32) -> &'a i32 {...}
```

生命周期 `'a` 表示返回值的生命周期必须在参数 `x` 的生命周期内,即返回值的生命周期是参数和返回值的最大共同生命周期。所以在返回值可以使用的地方,参数都必须存活,这也是常出现问题的地方。

最后看一下将这两个技巧结合起来的一个例子:

```rs
fn f<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {...}
```
{{< /admonition >}}

## 生命周期在函数上的省略规则

{{< image src="/images/rust/rust-lifetime-03.png" >}}

The Rust Reference: [Lifetime elision](https://doc.rust-lang.org/reference/lifetime-elision.html)

- Each elided lifetime in the parameters becomes a distinct lifetime parameter.
- If there is exactly one lifetime used in the parameters (elided or not), that lifetime is assigned to all elided output lifetimes.
- If the receiver has type `&Self` or `&mut Self`, then the lifetime of that reference to Self is assigned to all elided output lifetime parameters.

正如投影片所说,虽然有生命周期的省略规则,但有时并不符合我们的预期,这时候需要我们手动标注。这种情况常出现于可变引用 `&mut self` 的使用:

```rs
struct S {}

impl S {
fn as_slice_mut<'a>(&'a mut self) -> &'a [u8] {...}
}

let s: S = S{};
let x: &[u8] = s.as_slice_mut(); //---
... // |
... // | scope
... // |
// end of s's lifetime //---
```

在上面例子中,由于将方法 `as_slice_mut` 的可变引用参数和返回值的生命周期都标注为相同 `'a`,所以在范围 scope 中,在编译器看来 `s` 的可变引用仍然有效 (回想一下之前的参数和返回值的生命周期推导技巧),所以在这个范围内无法使用 `s` 的引用 (不管是可变还是不可变,回想一下 Rust 的引用规则),这是一个很常见的可变引用引起非预期的生命周期的例子,下一节会进一步介绍。

## 关注生命周期

{{< image src="/images/rust/rust-lifetime-04.png" >}}

```rs
fn insert_value<'a>(my_vec: &'a mut Vec<&'a i32>, value: &'a i32) {...}
```

这个例子和之前的例子很类似,同样的,使用我们的参数生命周期推导技巧,调用函数 `insert_value` 后,当参数 `vec``value` 的最大共同生命周期的范围很广时,这时就需要注意,在这个范围内,我们无法使用 `my_vec` 对应的 object 的任何其它引用 (因为编译器会认为此时还存在可变引用 `my_vec`),从而编译错误。为避免这种非预期的生命周期,应当将函数原型改写如下:

```rs
fn insert_value<'a, 'b>(my_vec: &'a mut Vec<&'b i32>, value: &'b i32) {...}
```

> 这样改写会包含一个隐式的生命周期规则: `'a` $\leq$ `'b`,这很好理解,容器的生命周期应该比所引用的 object 短。
## Documentations

这里列举视频中一些概念相关的 documentation
Expand All @@ -66,3 +151,4 @@ repost:
## References

- [LifetimeKata](https://tfpk.github.io/lifetimekata/)
- [The Rust Reference](https://doc.rust-lang.org/reference/)
10 changes: 5 additions & 5 deletions docs/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<body data-header-desktop="sticky" data-header-mobile="auto"><script>(window.localStorage?.getItem('theme') ? localStorage.getItem('theme') === 'dark' : ('auto' === 'auto' ? window.matchMedia('(prefers-color-scheme: dark)').matches : 'auto' === 'dark')) && document.body.setAttribute('data-theme', 'dark');</script><div class="wrapper" data-page-style="normal"><header class="desktop animate__faster" id="header-desktop">
<div class="header-wrapper">
<div class="header-title">
<a href="/" title="KZnight&#39;s Blog"><img loading="lazy" src="/fixit.min.svg" alt="KZnight&#39;s Blog" data-title="KZnight&#39;s Blog" class="logo" style="background: url(/images/loading.min.svg) no-repeat center;" onload="this.title=this.dataset.title;for(const i of ['style', 'data-title','onerror','onload']){this.removeAttribute(i);}this.dataset.lazyloaded='';" onerror="this.title=this.dataset.title;for(const i of ['style', 'data-title','onerror','onload']){this.removeAttribute(i);}"/><span class="header-title-text">KZnight&#39;s Blog</span></a><span class="header-subtitle"></span></div>
<a href="/" title="KZnight&#39;s Blog"><img loading="lazy" src="/fixit.min.svg" data-title="KZnight&#39;s Blog" data-alt="KZnight&#39;s Blog" class="logo" style="background: url(/svg/loading.min.svg) no-repeat center;" onload="this.title=this.dataset.title;this.alt=this.dataset.alt;for(const i of ['style', 'data-title','data-alt','onerror','onload']){this.removeAttribute(i);}this.dataset.lazyloaded='';" onerror="this.title=this.dataset.title;this.alt=this.dataset.alt;for(const i of ['style', 'data-title','data-alt','onerror','onload']){this.removeAttribute(i);}"/><span class="header-title-text">KZnight&#39;s Blog</span></a><span class="header-subtitle"></span></div>
<nav>
<ul class="menu"><li class="menu-item">
<a
Expand Down Expand Up @@ -65,7 +65,7 @@
<div class="header-container">
<div class="header-wrapper">
<div class="header-title">
<a href="/" title="KZnight&#39;s Blog"><img loading="lazy" src="/fixit.min.svg" alt="/fixit.min.svg" data-title="/fixit.min.svg" class="logo" style="background: url(/images/loading.min.svg) no-repeat center;" onload="this.title=this.dataset.title;for(const i of ['style', 'data-title','onerror','onload']){this.removeAttribute(i);}this.dataset.lazyloaded='';" onerror="this.title=this.dataset.title;for(const i of ['style', 'data-title','onerror','onload']){this.removeAttribute(i);}"/><span class="header-title-text">KZnight&#39;s Blog</span></a><span class="header-subtitle"></span></div>
<a href="/" title="KZnight&#39;s Blog"><img loading="lazy" src="/fixit.min.svg" data-title="/fixit.min.svg" data-alt="/fixit.min.svg" class="logo" style="background: url(/svg/loading.min.svg) no-repeat center;" onload="this.title=this.dataset.title;this.alt=this.dataset.alt;for(const i of ['style', 'data-title','data-alt','onerror','onload']){this.removeAttribute(i);}this.dataset.lazyloaded='';" onerror="this.title=this.dataset.title;this.alt=this.dataset.alt;for(const i of ['style', 'data-title','data-alt','onerror','onload']){this.removeAttribute(i);}"/><span class="header-title-text">KZnight&#39;s Blog</span></a><span class="header-subtitle"></span></div>
<div class="menu-toggle" id="menu-toggle-mobile">
<span></span><span></span><span></span>
</div>
Expand Down Expand Up @@ -130,16 +130,16 @@ <h1 id="error-emoji"></h1>
document.getElementById('error-emoji').appendChild(document.createTextNode(emojiArray[Math.floor(Math.random() * emojiArray.length)]));
})();
</script></main><footer class="footer">
<div class="footer-container"><div class="footer-line powered"><a href="https://gohugo.io/" target="_blank" rel="external nofollow noopener noreferrer" title="Hugo 0.121.1"><img class="hugo-icon" src="/images/hugo.min.svg" alt="Hugo logo" /> Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/hugo-fixit/FixIt" target="_blank" rel="external" title="FixIt v0.3.2-RC"><img class="fixit-icon" src="/images/fixit.min.svg" alt="FixIt logo" /> FixIt</a>
<div class="footer-container"><div class="footer-line powered"><a href="https://gohugo.io/" target="_blank" rel="external nofollow noopener noreferrer" title="Hugo 0.121.2">Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/hugo-fixit/FixIt" target="_blank" rel="external" title="FixIt v0.2.18-lts.5"><img class="fixit-icon" src="/fixit.min.svg" alt="FixIt logo" />&nbsp;FixIt</a>
</div><div class="footer-line copyright" itemscope itemtype="http://schema.org/CreativeWork"><i class="fa-regular fa-copyright fa-fw" aria-hidden="true"></i>
<span itemprop="copyrightYear">2021 - 2024</span><span class="author" itemprop="copyrightHolder">
<a href="https://github.com/ccrysisa"target="_blank" rel="external nofollow noopener noreferrer">ccrysisa</a></span><span class="license footer-divider"><a rel="license external nofollow noopener noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a></span></div><div class="footer-line visitor">
<a href="https://github.com/ccrysisa"target="_blank" rel="external nofollow noopener noreferrer">ccrysisa</a></span><span class="license footer-divider"><a rel="license external nofollow noopener noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a></span></div><div class="footer-line statistics"></div><div class="footer-line visitor">
<span id="busuanzi_container_site_uv" title='总访客数'><i class="fa-regular fa-user fa-fw" aria-hidden="true"></i>&nbsp;<span id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin fa-fw" aria-hidden="true"></i></span></span><span id="busuanzi_container_site_pv" class="footer-divider" title='总访问量'><i class="fa-regular fa-eye fa-fw" aria-hidden="true"></i>&nbsp;<span id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin fa-fw" aria-hidden="true"></i></span></span>
</div></div>
</footer></div><div class="widgets"><div class="fixed-buttons animate__faster d-none"><div class="fixed-button back-to-top" role="button" aria-label="回到顶部"><i class="fa-solid fa-arrow-up fa-fw" aria-hidden="true"></i><span class="variant-numeric d-none">0%</span>
</div></div><div id="mask"></div><noscript>
<div class="noscript-warning">FixIt 主题在启用 JavaScript 的情况下效果最佳。</div>
</noscript>
</div><link rel="preload" href="/lib/katex/katex.min.css" as="style" onload="this.removeAttribute('onload');this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/lib/katex/katex.min.css"></noscript><link rel="stylesheet" href="/lib/cookieconsent/cookieconsent.min.css"><script src="/lib/autocomplete/autocomplete.min.js" defer></script><script src="/lib/sharer/sharer.min.js" async defer></script><script src="/lib/katex/katex.min.js" defer></script><script src="/lib/katex/auto-render.min.js" defer></script><script src="/lib/katex/copy-tex.min.js" defer></script><script src="/lib/katex/mhchem.min.js" defer></script><script src="/lib/cookieconsent/cookieconsent.min.js" defer></script><script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async defer></script><script>window.config={"code":{"copyTitle":"复制到剪贴板","editLockTitle":"锁定可编辑代码块","editUnLockTitle":"解锁可编辑代码块","editable":true,"maxShownLines":20},"cookieconsent":{"content":{"dismiss":"同意","link":"了解更多","message":"本网站使用 Cookies 来改善您的浏览体验。"},"enable":true,"palette":{"button":{"background":"#f0f0f0"},"popup":{"background":"#1aa3ff"}},"theme":"edgeless"},"enablePWA":true,"math":{"delimiters":[{"display":true,"left":"$$","right":"$$"},{"display":true,"left":"\\[","right":"\\]"},{"display":true,"left":"\\begin{equation}","right":"\\end{equation}"},{"display":true,"left":"\\begin{equation*}","right":"\\end{equation*}"},{"display":true,"left":"\\begin{align}","right":"\\end{align}"},{"display":true,"left":"\\begin{align*}","right":"\\end{align*}"},{"display":true,"left":"\\begin{alignat}","right":"\\end{alignat}"},{"display":true,"left":"\\begin{alignat*}","right":"\\end{alignat*}"},{"display":true,"left":"\\begin{gather}","right":"\\end{gather}"},{"display":true,"left":"\\begin{CD}","right":"\\end{CD}"},{"display":false,"left":"$","right":"$"},{"display":false,"left":"\\(","right":"\\)"}],"strict":false},"search":{"highlightTag":"em","maxResultLength":10,"noResultsFound":"没有找到结果","snippetLength":50}};</script><script src="/js/theme.min.js" defer></script></body>
<noscript><link rel="stylesheet" href="/lib/katex/katex.min.css"></noscript><link rel="stylesheet" href="/lib/cookieconsent/cookieconsent.min.css"><script src="/lib/autocomplete/autocomplete.min.js" defer></script><script src="/lib/lunr/lunr.min.js" defer></script><script src="/lib/lunr/lunr.stemmer.support.min.js" defer></script><script src="/lib/lunr/lunr.zh.min.js" defer></script><script src="/lib/sharer/sharer.min.js" async defer></script><script src="/lib/katex/katex.min.js" defer></script><script src="/lib/katex/auto-render.min.js" defer></script><script src="/lib/katex/copy-tex.min.js" defer></script><script src="/lib/katex/mhchem.min.js" defer></script><script src="/lib/cookieconsent/cookieconsent.min.js" defer></script><script src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async defer></script><script>window.config={"code":{"copyTitle":"复制到剪贴板","editLockTitle":"锁定可编辑代码块","editUnLockTitle":"解锁可编辑代码块","editable":true,"maxShownLines":20},"cookieconsent":{"content":{"dismiss":"同意","link":"了解更多","message":"本网站使用 Cookies 来改善您的浏览体验。"},"enable":true,"palette":{"button":{"background":"#f0f0f0"},"popup":{"background":"#1aa3ff"}},"theme":"edgeless"},"enablePWA":true,"math":{"delimiters":[{"display":true,"left":"$$","right":"$$"},{"display":true,"left":"\\[","right":"\\]"},{"display":true,"left":"\\begin{equation}","right":"\\end{equation}"},{"display":true,"left":"\\begin{equation*}","right":"\\end{equation*}"},{"display":true,"left":"\\begin{align}","right":"\\end{align}"},{"display":true,"left":"\\begin{align*}","right":"\\end{align*}"},{"display":true,"left":"\\begin{alignat}","right":"\\end{alignat}"},{"display":true,"left":"\\begin{alignat*}","right":"\\end{alignat*}"},{"display":true,"left":"\\begin{gather}","right":"\\end{gather}"},{"display":true,"left":"\\begin{CD}","right":"\\end{CD}"},{"display":false,"left":"$","right":"$"},{"display":false,"left":"\\(","right":"\\)"}],"strict":false},"search":{"highlightTag":"em","lunrIndexURL":"/index.json","lunrLanguageCode":"zh","lunrSegmentitURL":"/lib/lunr/lunr.segmentit.js","maxResultLength":10,"noResultsFound":"没有找到结果","snippetLength":50,"type":"lunr"}};</script><script src="/js/theme.min.js" defer></script></body>
</html>
47 changes: 47 additions & 0 deletions docs/baidu_urls.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
https://ccrysisa.github.io/posts/english/
https://ccrysisa.github.io/posts/linux2023/
https://ccrysisa.github.io/posts/rust-lifetime/
https://ccrysisa.github.io/posts/c-control-flow/
https://ccrysisa.github.io/posts/oerv-pretask/
https://ccrysisa.github.io/posts/deepin-kvm/
https://ccrysisa.github.io/posts/c-preprocessor/
https://ccrysisa.github.io/posts/subtying-and-variance/
https://ccrysisa.github.io/posts/c-recursion/
https://ccrysisa.github.io/posts/linux-hashtable/
https://ccrysisa.github.io/posts/c-function/
https://ccrysisa.github.io/posts/concurrency-ordering/
https://ccrysisa.github.io/posts/concurrency-concepts/
https://ccrysisa.github.io/posts/openeuler-riscv-qemu/
https://ccrysisa.github.io/posts/c-std-security/
https://ccrysisa.github.io/posts/orst/
https://ccrysisa.github.io/posts/linux-dev-review/
https://ccrysisa.github.io/posts/riscv-optimization-guide/
https://ccrysisa.github.io/posts/channels/
https://ccrysisa.github.io/posts/c-standards/
https://ccrysisa.github.io/posts/c-memory/
https://ccrysisa.github.io/posts/c-bitwise/
https://ccrysisa.github.io/posts/smart-pointers-and-interior-mutability/
https://ccrysisa.github.io/posts/c-numerics/
https://ccrysisa.github.io/posts/linux2023-lab0/
https://ccrysisa.github.io/posts/rust-tcp/
https://ccrysisa.github.io/posts/linux-quiz1/
https://ccrysisa.github.io/posts/linux-concepts/
https://ccrysisa.github.io/posts/iterators/
https://ccrysisa.github.io/posts/c-linked-list/
https://ccrysisa.github.io/posts/declarative-macros/
https://ccrysisa.github.io/posts/lifetime-annotations/
https://ccrysisa.github.io/posts/deepin20.9/
https://ccrysisa.github.io/posts/deepin-dragonos/
https://ccrysisa.github.io/posts/debug-gdb/
https://ccrysisa.github.io/posts/c-pointer/
https://ccrysisa.github.io/posts/nthu-computer-network/
https://ccrysisa.github.io/posts/c-specification/
https://ccrysisa.github.io/posts/git/
https://ccrysisa.github.io/posts/network/
https://ccrysisa.github.io/posts/binary-representation/
https://ccrysisa.github.io/posts/why-rust-/
https://ccrysisa.github.io/posts/git-learn/
https://ccrysisa.github.io/posts/ubuntu22.04lts/
https://ccrysisa.github.io/posts/gnu-linux-dev/
https://ccrysisa.github.io/posts/math/
https://ccrysisa.github.io/posts/hello_world/
Loading

0 comments on commit c5e3dea

Please sign in to comment.