用途:
lazy_static是在第一次调用时(运行时)进行初始化,而非编译时,而常用的静态变量是在编译时进行初始化,运行阶段分配内存空间。这是lazy_static和static本质的区别。
这样我们几乎可以在初始化块中执行所有操作,甚至可以读取运行时值。比如在"rust写os"相关代码中,使用自定义的TSS和gdt时,都需要使用lazy_static宏完成对TSS和gdt静态初始化。
lazy_static是可以给静态变量延迟赋值的宏。
使用这个宏,所有 static类型的变量可在执行的代码在运行时被初始化。 这包括任何需要堆分配,如vector或hash map,以及任何非常量函数调用。
首先说明一点,声明和赋值是两个不同的代码指令
即
static int xxx = yyy;相当于 static int xxx;//声明指令 和 xxx = yyy; //赋值指令
声明指令是为变量分配内存空间,赋值指令是把值保存到变量内存空间,声明指令在编译期间相对内存空间就已经被固定好,方法栈被创建时,就自动把变量和该内存空间联系起来。
分配内存空间,并初始化为0
声明语句在编译期间就已经为变量设定好内存相对地址了,即变量一上来就已经在栈的数据区分配好,即使代码指令没有执行,也不影响数据区的分配
https://www.cnblogs.com/JMatrix/p/8194009.html
使用场景
当我们想初始化一些静态变量。例如:
1
2
3
|
static AGE:u32 = 18;
static NAME:&str = "hery";
static ARRAY:[u8;2] = [0x18u8, 0x11u8];
|
这当然没问题,那有没有想过初始化动态的数组,vector,map? 例如:
1
2
|
static VEC:Vec<u8> = vec![0x18u8, 0x11u8];
static MAP: HashMap<u32, String> = HashMap::new();
|
结果是编译不通过,提示如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
error: `<std::vec::Vec<T>>::new` is not yet stable as a const fn
--> src\bin\u-lazy-static.rs:21:22
|
21 | static VEC:Vec<u8> = Vec::new();
| ^^^^^^^^^^
|
= help: in Nightly builds, add `#![feature(const_vec_new)]` to the crate attributes to enable
#静态调用仅限于常量函数、元组结构和元组变量
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> src\bin\u-lazy-static.rs:22:36
|
22 | static MAP: HashMap<u32, String> = HashMap::new();
|
|
E0015 错误提示: 只有 const 类型函数能被静态或常量表达式调用。
我还想在使用函数初始化静态变量:
1
2
3
4
5
|
fn mulit(i: u32) -> u32 {
i * 2
}
static PAGE:u32 = mulit(18);
|
这也编译不通过。
用lazy_static解决以上问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref VEC:Vec<u8> = vec![0x18u8, 0x11u8];
static ref MAP: HashMap<u32, String> = {
let mut map = HashMap::new();
map.insert(18, "hury".to_owned());
map
};
static ref PAGE:u32 = mulit(18);
}
fn mulit(i: u32) -> u32 {
i * 2
}
fn main() {
println!("{:?}", *PAGE);
println!("{:?}", *VEC);
println!("{:?}", *MAP);
}
|