logo
火山博客
导航

Rust中的变量有哪些?

2024-11-19
9阅读时间5分钟

变量声明

在Rust中,变量使用let关键字声明:

Rust
let x = 5;

默认情况下,Rust中的变量是不可变的(immutable)。

可变变量

要创建可变变量,使用mut关键字:

Rust
let mut y = 5;
y = 6; // 这是允许的

变量遮蔽(Shadowing)

Rust允许声明同名的新变量,新变量会遮蔽旧变量:

Rust
let x = 5;
let x = x + 1; // 新的x遮蔽了旧的x

变量类型

基本类型

Rust有几种基本类型:

  • 整数:i8, i16, i32, i64, i128, u8, u16, u32, u64, u128
  • 浮点数:f32, f64
  • 布尔值:bool
  • 字符:char
Rust
let i: i32 = 42;
let f: f64 = 3.14;
let b: bool = true;
let c: char = 'z';

复合类型

  • 元组(Tuple)
  • 数组(Array)
Rust
let tup: (i32, f64, u8) = (500, 6.4, 1);
let arr: [i32; 5] = [1, 2, 3, 4, 5];

字符串

Rust有两种主要的字符串类型:

String: 可增长的字符串 &str: 字符串切片

Rust
let s: String = String::from("hello");
let str_slice: &str = "world";

常量

常量使用const关键字声明,必须指定类型,且只能设置为常量表达式:

Rust
const MAX_POINTS: u32 = 100_000;

静态变量

静态变量有固定的内存地址,整个程序运行期间都存在 静态变量使用static关键字声明:

Rust
static LANGUAGE: &str = "Rust";

可变静态变量

注意:可变静态变量是可能的,但由于可能导致数据竞争,它们被认为是不安全的,需要在unsafe块中进行。

Rust
static mut COUNTER: u32 = 0;

fn main() {
    unsafe {
        COUNTER += 1;
        println!("Counter: {}", COUNTER);
    }
}

生命周期

生命周期是Rust中的一个重要概念,它确保引用的有效性:

Rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

作用域

变量的作用域通常限定在它被创建的块内:

Rust
{
    let x = 5;
    // x 只在这个块内有效
}
// 这里 x 无效

所有权(Ownership)

Rust通过所有权系统管理内存:

  • 每个值只能有一个所有者
  • 当所有者离开作用域,值将被丢弃
Rust
let s1 = String::from("hello");
let s2 = s1; // s1的所有权移动到s2
// println!("{}", s1); // 这会导致编译错误

借用(Borrowing)

借用允许在不获取所有权的情况下使用值:

Rust
fn calculate_length(s: &String) -> usize {
    s.len()
}

let s1 = String::from("hello");
let len = calculate_length(&s1);

注意:在同一作用域内,要么只能有一个可变引用,要么可以有任意数量的不可变引用。

切片(Slices)

切片允许引用集合中的一部分连续元素:

Rust
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];

全局变量

在Rust中,全局变量的处理比较特殊,主要有以下几种方式:

常量(Const)

Rust
const MAX_HEALTH: u32 = 100;

fn main() {
    println!("Max health is: {}", MAX_HEALTH);
}

静态变量(Static)

Rust
static LANGUAGE: &str = "Rust";

fn main() {
    println!("Language: {}", LANGUAGE);
}

线程安全的全局变量

对于需要在多线程环境中安全使用的全局变量,可以使用std::sync模块中的类型:

Rust
use std::sync::Mutex;
use lazy_static::lazy_static;

lazy_static! {
    static ref ARRAY: Mutex<Vec<u32>> = Mutex::new(vec![]);
}

fn main() {
    ARRAY.lock().unwrap().push(1);
    println!("Array: {:?}", ARRAY.lock().unwrap());
}

这里使用了lazy_static宏来创建一个线程安全的全局变量。

使用外部crate实现全局变量

一些第三方crate提供了更方便的全局变量实现方式,例如once_cell:

Rust
use once_cell::sync::Lazy;

static HASHMAP: Lazy<std::collections::HashMap<i32, String>> = Lazy::new(|| {
    let mut m = std::collections::HashMap::new();
    m.insert(13, "Spica".to_string());
    m.insert(74, "Hoyten".to_string());
    m
});

fn main() {
    println!("Entry 74: {:?}", HASHMAP.get(&74));
}

全局变量的最佳实践

  1. 优先使用const来定义全局常量。
  2. 如果需要可变性,考虑使用线程安全的类型如Mutex或AtomicTypes。
  3. 避免使用可变静态变量,因为它们是不安全的。
  4. 考虑使用lazy_static或once_cell等crate来简化复杂全局变量的初始化。
2024 © Powered by
hsBlog
|
后台管理