Rust代码示例——15.4.6.生命周期的边界

如同泛型一般,生命周期也可以使用边界。符号“:”在这有不同的意义,但是符号“+”是相同的。注意下面的要点:

  1. T: ‘a:所有关于T的引用必须比“’a”的生命周期更长。
  2. T: Trait + ‘a:类型T必须实现接口Trait,所有关于T的引用都要比 ’a的生命周期更长。

下面的示例展示了上面要点中的语法在关键字where之后使用方法:

use std::fmt::Debug; // Trait to bound with.


#[derive(Debug)]

struct Ref<'a, T: 'a>(&'a T);

// `Ref` contains a reference to a generic type `T` that has

// some lifetime `'a` unknown by `Ref`. `T` is bounded such that any

// *references* in `T` must outlive `'a`. Additionally, the lifetime

// of `Ref` may not exceed `'a`.


// A generic function which prints using the `Debug` trait.

fn print<T>(t: T) where

    T: Debug {

    println!("`print`: t is {:?}", t);

}


// Here a reference to `T` is taken where `T` implements

// `Debug` and all *references* in `T` outlive `'a`. In

// addition, `'a` must outlive the function.

fn print_ref<'a, T>(t: &'a T) where

    T: Debug + 'a {

    println!("`print_ref`: t is {:?}", t);

}


fn main() {

    let x = 7;

    let ref_x = Ref(&x);


    print_ref(&ref_x);

    print(ref_x);

}
代码解析
// 语法类比:

// 泛型约束       T: Trait

// 生命周期约束   T: 'a

// 混合约束       T: Trait + 'a
带有生命周期的泛型结构体
#[derive(Debug)]

struct Ref<'a, T: 'a>(&'a T);

// 解读:

// 1. `T: 'a` 表示类型T中的所有引用必须比`'a`存活更久

// 2. 结构体本身不能超过`'a`的生命周期

// 效果:确保被引用的数据比结构体实例存活更久
泛型函数的基本约束
fn print<T>(t: T) where

    T: Debug {

    println!("`print`: t is {:?}", t);

}

// 普通泛型约束:只要求实现Debug trait
带有生命周期约束的引用函数
fn print_ref<'a, T>(t: &'a T) where

    T: Debug + 'a {

    println!("`print_ref`: t is {:?}", t);

}

// 双重约束:

// 1. T: Debug   —— 必须实现Debug trait

// 2. T: 'a     —— T中的所有引用必须比`'a`存活更久

// 额外保证:函数不能超过`'a`的生命周期
主函数解析
fn main() {

    let x = 7;                  // 数据生命周期开始

    let ref_x = Ref(&x);        // 创建引用包装

    

    print_ref(&ref_x);          // 合法:x和ref_x都满足生命周期要求

    print(ref_x);               // 转移所有权到print函数

}

// 关键点:x的生命周期包含所有使用场景
生命周期边界的三层含义
  1. T: a的深层含义

当T是引用类型时:直接要求该引用比‘’a’长。

当T包含嵌套引用时:所有层级的引用都必须比‘’a’长。

当T是值类型时:自动满足(因不包含引用)

  1. 与泛型约束的结合
fn example<'a, T>(t: &'a T) where

    T: Debug + 'a + Send

// 解读:

// 1. 必须实现Debug和Send trait

// 2. 所有内部引用必须比`'a`长
  1. where 子句的优势

提高复杂约束的可读性

允许将约束与函数签名分离

为什么需要这种设计
防止结构体有无效引用
struct Invalid<'a> {

    data: &'a str  // 必须保证被引用的字符串比结构体存活久

}
支持嵌套引用场景
struct Complex<'a> {

    inner: &'a Vec<&'a String>  // 字符串和Vec都必须比'a长

}
保证trait对象的可靠性
trait Trait {}

fn make_object<'a>(t: &'a (dyn Trait + 'a))

// 确保trait对象内部引用有效
实际编译器的处理

当使用下面的代码:

fn print_ref<'a, T>(t: &'a T) where T: 'a

编译器处理流程:

  1. 检查传入的&’a T。
  2. 递归分析T类型中的所有引用。
  3. 验证每个引用是否确实比’a存活更久

如果发现任何引用比’a存活时间短,立即报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值