关于Rust中常见的生命期的“例子”(一)

一、说明

类型 含义 样例
T 1、所有可能的类型集合或其中一个具体类型 T,&T,&&T;i32,&i32,&&i32
&T T类型的引用(共享不可变的引用) &i32, &&i32
&mut T T类型的可变引用(独占可变引用) &mut i32

T类型是&T和&mut T的超集;

“可变不共享,共享不可变”

在Rust中一个变量的生命期是指其所指向的内存地址中数据有效的“一段时期”;而这段时期是有编译器静态分析得出的,有效性是由编译器保证的

二、样例

1、T 只包含所有权类型

类型 T &T &mut T
样例 i32 &i32 &mut i32

其中T包含全体所有权类型;&T包括全体不可变引用;&mut T包括全体可变引用;
其中T、&T、&mut T是不相交的有限集合

实际情况如下

类型 T &T &mut T
例子 i32,&i32,&muti32,&&i32,&mut &mut i32,... &i32,&&i32,&&mut i32,... &mut i32, &mut &mut i32, &mut &i32,...

T, &T, &mut T都是无限集合; T是&T和&mut T的超集(由于可引用类型T自身无限次),且&T和&mut T是不相交的集合

trait TestTrait {}


impl<T> TestTrait for T {}      // target-1


impl<T> TestTrait for &T {}     // target-2


impl<T> TestTrait for &mut T {} // target-3

上述代码是不能编译通过的:

error[E0119]: conflicting implementations of trait `TestTrait` for type `&_`
 --> src/bin/trait_generic_demo.rs:6:1
  |
4 | impl <T> TestTrait for T{}
  | ------------------------ first implementation here
5 | 
6 | impl<T> TestTrait for &T {}
  | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`

所以验证了“T是&T和&mut T的超集”,也就意味着“target-1”的代码包括了“target-2”和“target-3”的实现;
而若是注释掉“target-1”的代码,其他不变,则编译也是OK的,说明了“&T和&mut T是不相交的集合”

2、若是 T:'static,那么T的生命周期就会直到程序结束为止都一定是有效的

  • T:'static 应视为T有着'static的生命周期 ???
  • &'static T和T:'static 是一回事 ???
  • 若T:'static 则T一定不可变的 ???
  • 若T: 'static 则只能编译期创建 ???
    当首次接触'static生命周期,更多是如下的例子
let str_literal: &'static str = "字符串字面量";

这里的“字符串字面量”会被硬编码到编译出来的二进制文件中,并在运行时被加载到只读内存中,在整个运行期间有效且不可变的,使其生命周期为'static。 ???

举个例子:

static strs: [&str; 3] = ["hello", "world", "yes"];
static mut mut_strs: [&str; 3] = ["hello", "world", "yes"];

fn main() {
    // 错误信息
    // error[E0594]: cannot assign to `strs[_]`, as `strs` is an immutable static item
    //  --> src/bin/static_var_demo.rs:7:5
    //   |
    // 7 |     strs[0] = "come_here";
    //   |     ^^^^^^^^^^^^^^^^^^^^^ cannot assign
    // strs[0] = "come_here";
    unsafe {
        mut_strs[0] = "come_here";
        assert_eq!("come_here", mut_strs[0]);
    }
}

从上面的示例中,得出关于静态变量

  • 只能在编译期创建
  • 默认情况下它们是不可变的,修改静态变量可通过unsafe
  • 在整个程序运行期间都有效
    那么静态变量的生命周期是不是就是'static? 具有'static生命周期的变量是否要遵守上述同样的规则?
    需要注意的的是带有'static生命周期注解的类型和一个被'static约束的类型是不一样的,后者是可以在运行时被动态分配的,能被安全的修改的,也可以被drop,其还能存活任意的时长;

区分&'static T和 T: 'static:

  • &'static T是一个指向T的不可变引用,其中T可被安全的无限期地持有,甚至可直到程序结束;要求T自身不可变且保证在引用创建后不会被move; T也并不需要在编译时创建;
  • T:'static 是指T可以被安全地无限期地持有,甚至可以直到程序结束;T:'static 在包括了全部的&'static T的同时,还包括了所有权类型; 数据的所有者保证,只要自身还持有数据的所有权,数据就不会失效,这样所有者能够安全的无限期的持有数据,直至程序结束;此时T满足'static生命周期的约束而非T有着'static 生命周期;
use rand;

/// &'static T 样例
fn  rand_str_generator() -> &'static str {
    let rand_str = rand::random::<u64>().to_string();
    Box::leak(rand_str.into_boxed_str()); // 存在“内存泄漏”
}

/// T: 'static样例
fn drop_static<T: 'static>(t: T) {
    std::mem::drop(t);
}

fn drop_static_demo() {
    let mut strings: Vec<String> = Vec::new();
    for _ in 0..10 {
        if rand::random() {
            let string = rand::random::<u64>().to_string();
            strings.push(string);
        }
    }

    for mut string in strings {
        string.push_str(" a mutation");
        println!("{:?}", string);
        drop_static(string);
    }

    println!("i am the end of the program");
}

fn main() {
   // &'static T
   let rand_str = rand_str_generator();
    println!("{:?}", rand_str);
    // T: 'static 样例
    drop_static_demo();
}

关键点:

  • T: 'static 应当视为 “T 满足 'static 生命周期约束”
  • 若 T: 'static 则 T 可以是一个有 'static 生命周期的引用类型 或 是一个所有权类型
  • 因为 T: 'static 包括了所有权类型,所以 T
    1. 可以在运行时动态分配
    2. 不需要在整个程序运行期间都有效
    3. 可以安全,自由地修改
    4. 可以在运行时被动态的 drop
    5. 可以有不同长度的生命周期

(待续)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容