有几个问题似乎与我遇到的问题有关.例如,请看这里和这里.基本上我正在尝试String在本地函数中构建一个函数,但是然后将其作为一个函数返回&str.切片不起作用,因为寿命太短.我无法str直接在函数中使用,因为我需要动态构建它.但是,我也不想返回a,String因为一旦它构建完成,它进入的对象的性质就是静态的.有没有办法让我的蛋糕也吃?
这是一个最小的非编译复制:
fn return_str<'a>() -> &'a str {
let mut string = "".to_string();
for i in 0..10 {
string.push_str("ACTG");
}
&string[..]
}
Run Code Online (Sandbox Code Playgroud)
Vla*_*eev 61
不,你不能这样做.至少有两种解释为何如此.
首先,请记住引用是借用的,即它们指向某些数据但不拥有它,它由其他人拥有.在这种特殊情况下,字符串(您要返回的切片)由函数拥有,因为它存储在局部变量中.
当函数退出时,它的所有局部变量都被销毁; 这涉及调用析构函数,析构函数String释放字符串使用的内存.但是,您希望返回指向为该字符串分配的数据的借用引用.这意味着返回的引用立即变为悬空 - 它指向无效的内存!
除此之外,还创建了Rust,以防止出现此类问题.因此,在Rust中,不可能返回指向函数局部变量的引用,这在C语言中是可能的.
还有另一种解释,稍微更正式一些.我们来看看你的功能签名:
fn return_str<'a>() -> &'a str
Run Code Online (Sandbox Code Playgroud)
请记住,生命周期和泛型参数都是参数:它们由函数的调用者设置.例如,某些其他函数可能会像这样调用它:
let s: &'static str = return_str();
Run Code Online (Sandbox Code Playgroud)
这要求'a是'static,但它当然是不可能的-你的函数不引用返回到静态存储器,它返回一个严格较小一生的参考.因此,这样的函数定义是不合理的,并且被编译器禁止.
无论如何,在这种情况下,你需要返回一个拥有类型的值,在这种特殊情况下,它将是一个拥有的String:
fn return_str() -> String {
let mut string = String::new();
for _ in 0..10 {
string.push_str("ACTG");
}
string
}
Run Code Online (Sandbox Code Playgroud)
您可以选择泄漏内存以将 a 转换String为 a &'static str:
fn return_str() -> &'static str {
let string = "ACTG".repeat(10);
Box::leak(string.into_boxed_str())
}
Run Code Online (Sandbox Code Playgroud)
在许多情况下,这是一个非常糟糕的主意,因为每次调用此函数时内存使用量都会永远增长。
如果您想每次调用都返回相同的字符串,请参见:
在某些情况下,您会传递一个字符串切片,并且可能有条件地想要创建一个新字符串。在这些情况下,您可以返回Cow。这将在可能的情况下提供参考,String否则将为拥有:
use std::borrow::Cow;
fn return_str<'a>(name: &'a str) -> Cow<'a, str> {
if name.is_empty() {
let name = "ACTG".repeat(10);
name.into()
} else {
name.into()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8961 次 |
| 最近记录: |