首页 > 其他分享 >RUST 每日一省:全局变量

RUST 每日一省:全局变量

时间:2023-09-17 10:06:04浏览次数:49  
标签:lazy 一省 常量 静态 static 使用 全局变量 RUST APPLE


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

常量

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

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

const HEADER: u64 = 32;
fn main() {
    println!("{:?}", HEADER);
}

静态

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

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

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

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!宏,可用于初始化任何能够从程序中的任何位置全局访问的动态类型。

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

标签:lazy,一省,常量,静态,static,使用,全局变量,RUST,APPLE
From: https://blog.51cto.com/u_1334935/7499538

相关文章

  • 用Rust手把手编写一个Proxy(代理), 准备篇, 动手造轮子
    用Rust手把手编写一个Proxy(代理),准备篇,动手造轮子wmproxy将实现http/https代理,socks5代理,后续将实现websocket代理,内外网穿透等,会将实现过程分享出来,希望感兴趣的可以一起参与参与项目++wmproxy++gite:https://gitee.com/tickbh/wmproxygithub:https://git......
  • rust_trait个人理解
    0概述什么是traitrust中有许许多多的类型(枚举、结构体...),如果这些不同类型,都有类似的行为,我们把这个行为抽象出来,把他定义为一个特征(trait)一个trait中可以包含,一个或者一组行为,表现形式就是方法or函数1特征约束1.1特征约束1.2特征做函数参数的语法糖真特么nb,看下......
  • Rust 开发命令行工具(上)
    ❝你必须按所想去生活,否则只能按生活去想。--王小波❞大家好,我是「柒八九」。作为一个前端/Rust/AI知识博主,之前的文章中,大部分篇幅都是关于前端的知识分享,而对Rust和AI的内容只是做了几篇内容梳理和介绍。而,我们今后的重心也会逐渐偏移,势必能达到前端/Rust/AI「三足鼎立」的局面......
  • [转载]TCL全局变量与双冒号变量
    在TCL中,以下代码之间有何区别:代码globalMyVarsetMyVar5和代码set::MyVar5据我了解,::MyVar表示MyVar将是一个全局变量。那么区别是什么呢?1个答案:答案0:(得分:4)如果这是在过程中,则设置哪个变量或放入哪个值没有功能上的区别。(global在过程之外以及其他对......
  • 用 Rust 的 declarative macro 做了个小东西
    最近几天在弄ddnspod的时候,写了个宏:custom_meta_struct解决什么问题#[derive(Debug,Clone,serde::Serialize,serde::Deserialize)]structActionA{url:String,//https://example.comversion:String,//v1.2.3a:u64,//...}#[derive(Deb......
  • 同一类内部,类属性通用 类的继承,实例属性通用,类属性不通用 解决办法: 声明为全局变
    '''属性的继承'''classClass_1:importpandasaspd#储存pd,但不储存pandasprint(pd)#无需实例化deffun_1(pd=pd):print(pd)fun_1()#无需实例化def__init__(self,pd=pd):print(pd)self.pd=pd......
  • rust 多线程
    多线程之间的通信和内存共享常见方式usestd::sync::mpsc;usestd::thread;usestd::sync::{Arc,Mutex};structUser{name:String}fnmain(){//Arc通过共享内存在线程间通信数据不可修改(所以这里使用的不可变引用)letusr_raw=Arc::new(User{......
  • Python中跨越多个文件使用全局变量
    这个琐碎的指南是关于在Python中跨多个文件使用全局变量。但是在进入主题之前,让我们简单地看看全局变量和它们在多个文件中的用途。Python中的全局变量全局变量是不属于函数范围的变量,可以在整个程序中使用。这表明全局变量也可以在函数体内部或外部使用。让我们看一个例子:......
  • 局部变量和全局变量
    变量的作用域:局部变量全局变量 1)局部变量:在一个函数内部定义的变量或者函数的形参,统称为局部变量。eg:voidf(inti){intj=20;}     i和j都是局部变量2)全局变量:在所有函数外部的变量叫......
  • 文盘Rust——子命令提示,提高用户体验
    上次我们聊到CLI的领域交互模式。在领域交互模式中,可能存在多层次的子命令。在使用过程中如果全评记忆的话,命令少还好,多了真心记不住。频繁--help也是个很麻烦的事情。如果每次按'tab'键就可以提示或补齐命令是不是很方便呢。这一节我们就来说说'autocommplete'如何实现。......