关于Rust生命周期的疑问:字符串常量引用在变量超出作用域后仍可正常使用的原因
关于Rust生命周期的疑问:字符串常量引用在变量超出作用域后仍可正常使用的原因
嘿,你观察得特别细致!这个问题的关键确实和字符串常量的静态生命周期密切相关,咱们把这件事掰扯明白:
首先,得先搞懂Rust里字符串常量的本质——像"hello"、"world"这种用双引号直接写的字符串,并不是存储在栈上的局部临时变量,而是会被编译进程序的二进制可执行文件里。从程序启动的那一刻起,它们就被加载到内存中,直到程序完全退出才会被释放。这种贯穿整个程序运行周期的生命周期,在Rust里被标记为'static。
再看你代码里的细节(我帮你补全了合理的display函数实现):
fn main() { let a: &str = "hello"; let x: &str; let y: &str; { let b: &str = "world"; x = display(a, b, true); y = display(a, b, false); } println!("{}", x); // 正常打印 println!("{}", y); // 正常打印 } fn display<'a>(s1: &'a str, s2: &'a str, choose_first: bool) -> &'a str { if choose_first { s1 } else { s2 } }
这里的变量b只是一个指向静态字符串的引用,当这个内部作用域结束时,被销毁的只是b这个引用变量本身(它在栈上占用的一小片内存),但它指向的"world"字符串本体,依然安安稳稳待在静态内存区域里,根本没被回收。
然后看display函数,它返回的引用的生命周期是输入参数中较短的那个,但因为a和b指向的都是'static的字符串,所以返回的引用自然也继承了'static生命周期。哪怕承载引用的变量b已经被销毁,返回的x和y指向的还是那个一直存在的静态字符串,所以后续打印完全没问题。
对比一下就能更清楚:如果b是一个栈上的String(比如let b = String::from("world")),那当作用域结束时,b对应的堆内存会被释放,这时候再用它的引用就会触发Rust的生命周期检查错误——但字符串常量是特殊的,它们的生命周期足够长,根本不会有这个问题。
内容来源于stack exchange
相关产品推荐
相关产品推荐

