RUST 每日一省:全局变量

Rust中允许存在全局变量。它们一般有两种:常数和静态值。

常量

我们使用关键字 const 来创建常量。由于常量未使用关键字 let 声明,因此在创建它们时必须指定类型。常量只能进行简单赋值,并且没有固定的内存地址,无论它们在何处使用都会被内联。

常量不能遮蔽,不能重复定义。也就是说,不存在内层或后面作用域定义的常量去遮蔽外层或前面定义的同名常量的情况。常量一旦定义后就永远不可变更和重新赋值。

rust 复制代码
const HEADER: u64 = 32;
fn main() {
    println!("{:?}", HEADER);
}

静态

静态变量使用 static关键字定义, 跟常量一样需要显式指明类型,静态变量的生命周期也是全局的,因为它具有固定的内存位置,并且在整个程序中作为单个(唯一)实例存在。

静态变量并非被分配到栈中, 也不是在堆中, 而是和程序代码一起被存储于静态存储区中。 静态存储区是伴随着程序的二进制文件的生成(编译时) 被分配的, 并且在程序的整个运行期都会存在。

静态变量默认同样不可修改,因此无法取得某个值的mut 引用。static 可以声明为 mut,但再访问它就是不安全的,需要使用unsafe。

rust 复制代码
static mut APPLE: u32 = 4;
static BANANA: u8 = 9;

fn main() {
    unsafe {
        println!("APPLEis {}", APPLE);
        APPLE= 42;
        println!("APPLE is now {}", APPLE);
        println!("BANANAis {}", BANANA);
    }
}

对比

常量和静态变量非常相似,但它们之间存在一些微妙的区别:

静态变量的值在内存中拥有固定的地址,使用它的值总是会访问到同样的数据。与之相反的是,常量则允许在任何被使用到的时候复制其数据。另外一个区别在于静态变量是可变的。需要注意的是,访问和修改可变的静态变量是不安全的 。

如果你不需要依赖静态的单例属性及其预定义的内存位置,而只需要其具体值,那么应该更倾向于使用常量。它们允许编译器进行更好的优化,并且更易于使用。

lazy_static

全局值只能在初始化时声明非动态的类型,并且在编译期,它在堆栈上的大小是已知的。例如,你不能将 HashMap 创建为静态值,因为它涉及堆分配。幸运的是,我们可以使用 HashMap 和其他动态集合类型(如 Vec)构造全局静态值,这是通过被称为lazy_static 的第三方软件包实现的。它暴露了 lazy_static!宏,可用于初始化任何能够从程序中的任何位置全局访问的动态类型。

rust 复制代码
use std::sync::Mutex;
lazy_static! {
    static ref ITEMS: Mutex<Vec<u64>> = {
        let mut v = vec![];
        v.push(9);
        v.push(2);
        v.push(1);
        Mutex::new(v)
    }
}

使用 lazy_static!宏声明的元素需要实现 Sync 特征。这意味着如果某个静态值可变,那么必须使用诸如 Mutex 或 RwLock 这样的多线程类型。

使用 lazy_static! 会在每次访问静态数据时造成微小的性能损失,因为其实现使用了为一次性初始化而设计的一个低级同步原语 std::sync::Once。在后台,每次访问懒静态数据,程序都要执行一次原子加载指令以检查初始化是否完成。

相关推荐
oak隔壁找我11 分钟前
MySQL中 SHOW FULL PROCESSLIST` 输出中 `State` 列的所有可能值
后端
上进小菜猪1 小时前
基于 YOLOv8 的面向文档智能处理的表格区域检测系统 [目标检测完整源码]
后端
oak隔壁找我1 小时前
JVM常用调优参数
java·后端
IT_陈寒5 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
晨星shine5 小时前
GC、Dispose、Unmanaged Resource 和 Managed Resource
后端·c#
蝎子莱莱爱打怪5 小时前
OpenClaw 从零配置指南:接入飞书 + 常用命令 + 原理图解
java·后端·ai编程
倚栏听风雨6 小时前
【ES避坑指南】明明存的是 "CodingAddress",为什么 term 查询死活查不到?彻底搞懂 text 和 keyword
后端
程序员爱钓鱼6 小时前
Go 操作 Windows COM 自动化实战:深入解析 go-ole
后端·go·排序算法
回家路上绕了弯6 小时前
深入解析Agent Subagent架构:原理、协同逻辑与实战落地指南
分布式·后端
子玖7 小时前
实现微信扫码注册登录-基于参数二维码
后端·微信·go