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。在后台,每次访问懒静态数据,程序都要执行一次原子加载指令以检查初始化是否完成。

相关推荐
魔镜前的帅比2 小时前
(开源项目)x-claw (设计)
python·ai·rust·开源
Cicada1282 小时前
ccvt:一个用 Rust 写的中国地图坐标系互转命令行工具
开发语言·后端·rust
1001101_QIA3 小时前
工控机网络配置
开发语言·数据库·php
明月_清风3 小时前
🤗 Hugging Face 模型上传完全指南:从本地到 Hub 的 4 种姿势
前端·后端·ai编程
程序员雷欧3 小时前
ThreadPoolExecutor 深度解析:从核心参数到源码实现的全面剖析
java·开发语言·jvm
catchadmin3 小时前
对标 npx 的 CPX PHP 的 Composer 包执行器
开发语言·php·composer
一位狮子座的程序员3 小时前
如何用RAG解决AI智能体的知识盲区?
开发语言·c#
神奇小汤圆4 小时前
疯了!Fastjson 又爆出严重安全漏洞,Spring Boot 项目赶紧自查
后端
吹什么轩4 小时前
c++复习:模拟实现list来更好的理解和应用list
开发语言·c++