面试题答案
一键面试内存布局不同
const
声明的常量- 存储位置:
const
声明的常量在编译时就会被求值并内联到使用它的地方。它不会在运行时占用独立的内存空间。例如:
在编译后的代码中,const FIVE: i32 = 5; fn main() { let x = FIVE + 3; }
FIVE
不会有单独的内存存储,let x = FIVE + 3;
这行代码在编译时会直接处理为let x = 5 + 3;
。- 类型要求:
const
常量的类型必须是Copy
类型,并且其值必须在编译时就能确定。这是因为它要内联到使用的地方,不能依赖运行时的计算。
- 存储位置:
static
声明的静态变量- 存储位置:
static
声明的静态变量有自己独立的内存地址,在程序的整个生命周期内存在于静态内存区域。例如:
static mut COUNTER: i32 = 0; fn main() { unsafe { COUNTER += 1; println!("COUNTER: {}", COUNTER); } }
COUNTER
在静态内存中有自己的存储位置,可以在运行时通过其地址来访问和修改(这里因为COUNTER
是mut
可变的,并且访问可变静态变量需要unsafe
块)。- 类型限制相对宽松:
static
变量可以是任何类型,包括非Copy
类型。不过如果是可变的static
变量(mut
修饰),访问时需要unsafe
代码块,因为多个线程可能同时访问它,容易引发数据竞争。
- 存储位置:
对程序运行影响举例
const
常量- 优点:由于内联,不会有额外的内存访问开销,提高了程序的运行效率。特别是在多次使用同一个常量值的情况下,不会因为重复存储常量值而浪费内存。例如在一个循环中多次使用
const
常量:
编译后,循环中的const ONE: i32 = 1; fn main() { for _ in 0..10 { let result = ONE + 2; println!("{}", result); } }
ONE
直接被替换为1
,没有额外的内存访问操作。- 缺点:如果常量值需要修改,那么需要修改源代码并重新编译整个程序,因为常量值是编译时确定的。
- 优点:由于内联,不会有额外的内存访问开销,提高了程序的运行效率。特别是在多次使用同一个常量值的情况下,不会因为重复存储常量值而浪费内存。例如在一个循环中多次使用
static
变量- 优点:可以在运行时修改其值,并且可以在程序的不同部分共享这个变量。例如在一个多函数的程序中共享一个静态计数器:
这里不同的函数可以通过静态变量static mut COUNTER: i32 = 0; fn increment_counter() { unsafe { COUNTER += 1; } } fn print_counter() { unsafe { println!("COUNTER: {}", COUNTER); } } fn main() { increment_counter(); increment_counter(); print_counter(); }
COUNTER
共享数据。- 缺点:由于存在于静态内存且生命周期长,可能会导致内存占用增加。而且可变静态变量的访问需要
unsafe
代码块,使用不当容易引发内存安全问题,如数据竞争(在多线程环境下)。