fn main() {
let s = "FOO";
let s_lower = s.to_lowercase().as_str();
println!("{}", s_lower);
}他说
3 | let s_lower = s.to_lowercase().as_str();
| ^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement然而,
fn main() {
let s = "FOO";
let s_lower = &s.to_lowercase();
println!("{}", s_lower);
}都没问题。
为什么?是因为&temp_string是一个不同于&str的&String吗?如果是这样的话,是怎么做的?
谢谢!
发布于 2022-02-23 08:17:54
来自“kmdreko& @sudo”的几个链接是有用的。
我理解为什么s.to_lowercase().to_str()不编译,但不知道为什么&s.to_lowercase()没有同样的问题。这叫做临时寿命延长,医生说:
let语句中表达式的临时作用域有时会扩展到包含let语句的块的作用域。这是在通常的临时作用域太小时,根据某些语法规则进行的。例如:
let x = &mut 0;
// Usually a temporary would be dropped by now, but the temporary for `0` lives
// to the end of the block.
println!("{}", x);我觉得这个特别的规则有点武断。这是一个关于为什么它不适用于我共鸣的temp.as_bytes()的原因的temp.as_bytes()。
令人惊讶的是,有一个RFC似乎想要使这更有规律,但不知何故不适用于这里。
这篇文章解释了为什么在某些情况下需要临时生命周期扩展。
我发现这个旧锈参考文献对于理解临时值也很有帮助,还有很多例子。
发布于 2022-02-23 06:37:17
这里有两点要说明。
&String和&str是不同的类型。前者是对动态堆字符串类型的引用,后者是对字符串部分的引用。我建议回顾一下片上锈蚀书的这个第二章。在第一个示例中,to_lowercase()的返回类型是String --它返回将由调用方拥有的String。但是,我们没有将这个返回值绑定到一个变量--我们试图先调用as_str(),然后将其结果绑定到s_lower。如果不首先绑定结果,as_str()就不能与to_lowercase()链接,因为它需要引用调用String,而调用String是不能在临时的情况下完成的。这是有问题的,因为在调用String as_str()之前,to_lowercase()返回的最终会被删除(被释放和不可使用),因为编译器意识到不能使用它。
为了更清楚地说明,他的第一个例子相当于:
fn main() {
let s = "FOO";
// temporary scope
{
let temporary = s.to_lowercase();
}
let s_lower = temporary.as_str();
}基于临时值规则,这种方法有望使临时值的生存期更加清晰。要修复第一个示例,您必须这样做:
fn main() {
let s = "FOO";
let s_lower = &s.to_lowercase();
let s_lower_slice = s_lower.as_str();
println!("{s_lower_slice}");
}这一点在答案@kmdreko链接上图中有进一步的解释。
https://stackoverflow.com/questions/71230066
复制相似问题