rust笔记11 生命周期引用有效性
函数参数等的生命周期
rust保证内存安全的手段之一是没有悬空的引用(指针),而这个靠编译期间强制生命周期检查实现。先给出生命周期的声明方式:
&i32 // i32的引用
&'a i32 // 带有显式声明周期的引用
&'a mut i32 // 带有显式生命周期的可变引用
考虑函数一个函数(该函数不会通过编译):
fn longer(x: &str, y: &str) -> &str {if x.len() > y.len() {x} else {y}
}
假设该函数能通过编译,而且在如下情景使用:
let x = String::from("foo");
let z;
{let y = String::from("hello world !");z = longer(x, y);
}
println!("{} is longer", z);
上述代码还会报错的,因为z
的引用在离开作用域后,就失效了,println
宏内部使用了一个悬空引用。
想要保证绝对内存安全,需要让返回的引用的有x
和y
中最短的生命周期,给出实际的实现方式:
fn longer<'a>(x: &'a str, y: &'a str) -> &'a str {if x.len() > y.len() {x} else {y}
}
这个声明,意味着返回的&str
有x
和y
中最短的生命周期。这种的强制声明,可以检测出之前代码段的缺陷。
使用’a
的方式,可以显式声明生命周期。生命周期语法是用于将函数的多个参数与其返回值的生命周期进行关联的。一旦他们形成了某种关联,Rust 就有了足够的信息来允许内存安全的操作并阻止会产生悬垂指针亦或是违反内存安全的行为。
结构体也可以采用类似的方式,代码实例:
struct Duck<'a, 'b, 'c> {name: &'a str,nick_name: &'b str,address: &'c str,
}
则Duck
结构实例化对象的生命周期一定是小于等于name
、nick_name
和address
中最小的那个。
省略生命周期
给出两个概念:
- 输入生命周期:函数的输入
- 输出生命周期:函数的返回值
三个省略规则:
- 每一个是引用的参数都有它自己的生命周期参数。换句话说就是,有一个引用参数的函数有一个生命周期参数:
fn foo<'a>(x: &'a i32)
,有两个引用参数的函数有两个不同的生命周期参数,fn foo<'a, 'b>(x: &'a i32, y: &'b i32)
,依此类推 - 如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数:
fn foo<'a>(x: &'a i32) -> &'a i32
- 如果方法有多个输入生命周期参数,不过其中之一因为方法的缘故为
&self
或&mut self
,那么self
的生命周期被赋给所有输出生命周期参数。这使得方法更容易读写,因为只需更少的符号
直接给出代码实例:
fn print(s: &str); // elided
fn print<'a>(s: &'a str); // expandedfn debug(lvl: u32, s: &str); // elided
fn debug<'a>(lvl: u32, s: &'a str); // expanded// In the preceding example, `lvl` doesn’t need a lifetime because it’s not a
// reference (`&`). Only things relating to references (such as a `struct`
// which contains a reference) need lifetimes.fn substr(s: &str, until: u32) -> &str; // elided
fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expandedfn get_str() -> &str; // ILLEGAL, no inputsfn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is ambiguousfn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expandedfn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expandedfn new(buf: &mut [u8]) -> BufWriter; // elided
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
结构体的生命周期
如果结构体的生命周期与外界的相关联,那么结构体的方法也需要声明对应的生命周期,直接给出代码实例:
struct Duck<'a, 'b, 'c> {name: &'a str,nick_name: &'b str,address: &'c str,
}impl<'a, 'b, 'c> Duck<'a, 'b, 'c> {fn foo(&self) {}
}fn main() {}
静态生命周期
let s: &'static str = "I have a static lifetime.";
在整个程序中都是可用的。
rust笔记11 生命周期引用有效性相关推荐
- day4 vue 学习笔记 组件 生命周期 数据共享 数组常用方法
系列文章目录 day1学习vue2笔记 vue指令 day2 学习vue2 笔记 过滤器 侦听器 计算属性 axios day3 vue2 学习笔记 vue组件 day4 vue 学习笔记 组件 生命 ...
- 008 Rust死灵书之生命周期
介绍 本系列录制的视频主要放在B站上Rust死灵书学习视频 Rust相关的源码资料在:https://github.com/anonymousGiga 笔记内容 今天我们跟大家聊一聊生命周期. 命周期 ...
- IOS学习笔记——ViewController生命周期详解
在我之前的学习笔记中讨论过ViewController,过了这么久,对它也有了新的认识和体会,ViewController是我们在开发过程中碰到最多的朋友,今天就来好好认识一下它.ViewContro ...
- react学习笔记(8)生命周期回顾与再认识
生命周期 生命周期是一个组件从创建到销毁的过程. 当组建实例被创建并且插入到DOM中,需要调用的函数,就是生命周期函数. 也就是说,组件加载完成前后.组件更新数据.组件销毁,所触发的一系列的方法. 1 ...
- Android笔记 activity生命周期 Tasks and back stack回退栈
正常打开一个应用,先后调用Activity的onCreate.onStart.onResume 正常退出一个应用,先后调用Activity的onPause.onStop.onDestroy(进程被杀死 ...
- android学习笔记---36_Activity生命周期
36_Activity生命周期 ----------------------------- 1.Activity生命周期,用于activity在运行时候受到一些突然事件的影响 ,例如:正在使用一个 ...
- PMP笔记之“生命周期”
提示:关于 项目生命周期.产品生命周期.开发生命周期的阐述. 文章目录 前言 一.项目生命周期 二.产品生命周期 三.开发命周期 总结 前言 关于项目生命周期.产品生命周期.开发生命周期的问题,一直不 ...
- Gavin小黑屋——Vue 学习笔记 :生命周期特点(先渲染HTML标签再渲染数据)
Vue基础 生命周期特点(先渲染HTML标签再渲染数据) 目录 Vue基础 生命周期特点(先渲染HTML标签再渲染数据) 一.Vue生命周期 Vue 的生命周期总共分为8个阶段:创建前/后,载 ...
- 游戏脚本和MonoBehaviour生命周期
一.游戏脚本 1.双击Project视图中, Script目录下的GameManager脚本 2.使用MonoDevelop编辑器打开 3.所有创建的用于添加到游戏对象上的脚本都必须继承自MonoBe ...
最新文章
- matlab在曲线给命名,matlab 利用xlsread画图,怎么将一组excel数据导入,通过matlab作图...
- 使用version遇到的那些坑
- C语言退出多层嵌套循环技巧
- 第19章 归档模式下的数据库恢复
- 对uC/OS-II内二维指针的研究
- 经常在比特币中看到的merkle树是什么?
- PTA第3章-9 字符串转换成十进制整数 (15 分)
- HTML5协议的,HTML5新增协议:WebSocket协议的实例
- 一步步学习微软InfoPath2010和SP2010--第八章节--使用InfoPath表单Web部件
- 构建灵活工作方式 戴尔最智能商用客户端产品线全面上市
- 《JSON笔记之三》---postman中传入json串
- windowsterminal设置初始大小_这是我见过最全面的金蝶操作详解了,从初始化到财务使用全流程...
- CAD数据与ArcGIS数据的互转换
- 路由器下一跳地址怎么判断_路由器的功能及工作原理
- python如何求列表中的众数_算法(LeetCode)六种方法求数组中的绝对众数
- cocoapods导入第三方库
- 【VS2010学习笔记】【函数学习】一(MFC+OpenCV2.4.7读取摄像头之WM_TIMER消息处理函数的添加问题)
- ONVIF协议基础概念
- SpringCloud项目启动
- 关于codeblocks音乐播放