RUST 静态生命周期和动态生命周期

图例

分配在堆和栈上的内存有其各自的作用域,它们的生命周期是动态的

全局变量、静态变量、字符串字母量、代码等内容,在编译时,会被编译到可执行文件中的 BSS/Data/RoData/Text 段,然后在加载时,装入内存

因而,它们的生命周期和进程的生命周期一致,所以静态的

所以,函数指针的生命周期也是静态,因为函数在Text 段中,只要进程活着,其内存一直存在

静态生命周期

概述

静态生命周期 Rust 中最长的生命周期,表示引用在整个程序运行期间都有效。这些数据通常存储在程序的只读内存区域,在程序启动时创建,在程序结束时销毁

特点

  1. 数据存在于整个程序运行期间
  2. 通常存储在静态内存区域
  3. 不需要运行时生命周期检查
  4. 最安全的引用类型

示例

rust 复制代码
// 字符串字面量具有 'static 生命周期
let static_str: &'static str = "Hello, World!";

// 静态变量也具有 'static 生命周期
static STATIC_INT: i32 = 42;
let static_ref: &'static i32 = &STATIC_INT;

// 函数返回 'static 生命周期
fn get_static_str() -> &'static str {
    "This string lives for the entire program"
}

// 在结构体中使用 'static 生命周期
struct StaticHolder {
    data: &'static str,
}

impl StaticHolder {
    fn new() -> Self {
        StaticHolder {
            data: "This data lives forever",
        }
    }
}

fn main() {
    let holder = StaticHolder::new();
    println!("{}", holder.data);
    
    let s = get_static_str();
    println!("{}", s);
    
    // 这些引用可以在任何地方使用,不会出现悬垂引用
    let long_lived_ref = static_str;
    println!("{}", long_lived_ref);
}

动态生命周期

概述

动态生命周期是指哪些在编译时无法确定具体持续时间,需要在运行时通过检查器验证的生命周期

这些生命周期通常与作用域相关,由编译器推断或通过生命周期参数明确指定

特点

  1. 生命周期在编译不确定,需要运行时检查
  2. 与特定作用域绑定
  3. 需要生命周期注解来帮助编译器验证安全性
  4. 更灵活,但需要更多编译器支持

例子

rust 复制代码
// 函数接受两个引用并返回一个引用,需要明确生命周期参数
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

// 结构体包含引用,需要生命周期参数
struct TextEditor<'a> {
    content: &'a str,
    selection: &'a str,
}

impl<'a> TextEditor<'a> {
    fn new(content: &'a str) -> Self {
        TextEditor {
            content,
            selection: "",
        }
    }
    
    fn select(&mut self, start: usize, end: usize) {
        self.selection = &self.content[start..end];
    }
}

fn main() {
    // 动态生命周期的示例
    let string1 = String::from("long string is long");
    let string2 = String::from("short");
    
    let result;
    {
        // 这两个引用有不同的生命周期
        let part1 = &string1;
        let part2 = &string2;
        
        // longest 函数要求两个参数有相同的生命周期 'a
        result = longest(part1, part2);
        println!("The longest string is: {}", result);
    } // part1 和 part2 在这里离开作用域
    
    // result 仍然有效,因为它引用的是 string1 或 string2 的一部分
    // 而 string1 和 string2 仍然在作用域内
    println!("Still can use: {}", result);
    
    // 文本编辑器示例
    let content = String::from("This is a long text content for the editor");
    let mut editor = TextEditor::new(&content);
    
    editor.select(5, 15);
    println!("Selection: {}", editor.selection);
    
    // 如果尝试在 content 离开作用域后使用 editor,会导致编译错误
    // {
    //     let local_content = String::from("local");
    //     let local_editor = TextEditor::new(&local_content);
    //     // local_editor 不能离开这个作用域,因为它的引用依赖于 local_content
    // }
    // println!("{:?}", local_editor); // 这会编译错误
}

总结

特性 静态生命周期 ('static) 动态生命周期
持续时间 整个程序运行期间 由作用域决定
内存位置 静态内存区域 栈或堆
安全性 绝对安全 需要编译器验证
灵活性
使用场景 字符串字面量、静态变量 函数参数、结构体字段
相关推荐
像是套了虚弱散7 小时前
DevEco Studio与Web联合开发:打造鸿蒙混合应用的全景指南
开发语言·前端·华为·harmonyos·鸿蒙
旭意7 小时前
C++蓝桥杯之结构体10.15
开发语言·c++
麦麦鸡腿堡8 小时前
Java的单例设计模式-饿汉式
java·开发语言·设计模式
简单点了8 小时前
go前后端项目的启动 、打包和部署
开发语言·后端·golang
爱吃山竹的大肚肚8 小时前
@Valid校验 -(Spring 默认不支持直接校验 List<@Valid Entity>,需用包装类或手动校验。)
java·开发语言
汤姆yu9 小时前
2026版基于python的协同过滤音乐推荐系统
开发语言·python
汤姆yu9 小时前
基于python的电子商务管理系统
开发语言·python
我是大咖9 小时前
C语言-贪吃蛇项目开发工具篇---ncursee库安装
c语言·开发语言
weixin_4454766810 小时前
Java并发编程——synchronized的实现原理与应用
java·开发语言·并发·synchronized
yi碗汤园10 小时前
【超详细】C#自定义工具类-StringHelper
开发语言·前端·unity·c#·游戏引擎