在 Rust 中将构造的字符串插入 Vec
Insert constructed string into Vec in Rust
现在我正在编写一个程序,我正在使用基于 for 循环中的条件构造的字符串更新 Vec
。我正在尝试做的(非常人为的)简化形式如下:
fn main() {
let mut arr = vec!["_"; 5];
for (i, chr) in "abcde".char_indices() {
arr[i] = &chr.to_string().repeat(3);
}
}
但是,我收到错误 temporary value dropped while borrowed
。关于在这里做什么的任何指示?
问题是arr
只持有引用,里面的字符串必须在别处拥有。一个可能的解决方法是简单地泄漏您在循环中创建的瞬态字符串。
fn main() {
let mut arr = vec!["_"; 5];
for (i, chr) in "abcde".char_indices() {
arr[i] = Box::leak(Box::new(chr.to_string().repeat(3)));
}
}
arr
的生命周期是main
方法的范围,而chr.to_string()
只在for循环体中有效。分配它会导致错误。
您可以使用 Vec<String>
而不是 Vec<&str>
来避免此问题。
fn main() {
let mut arr = vec!["_".to_string(); 5];
for (i, chr) in "abcde".char_indices() {
arr[i] = chr.to_string().repeat(3);
}
}
这里我们看到 String "_".to_string()
被复制了五次(效率不高)。我怀疑您的真实代码并非如此。
使用字符串也尝试 this 一个衬里:
let arr: Vec<String> = "abcde".chars().map(|c| c.to_string().repeat(3)).collect();
输出:
["aaa", "bbb", "ccc", "ddd", "eee"]
正如其他人所提到的,您正在创建的 String
必须 由某人拥有,否则它们最终会被丢弃。当编译器检测到这种删除发生时您的数组仍然保留对它们的引用,它会抱怨。
你需要考虑谁需要拥有这些价值。如果您最终的阵列是他们居住的自然场所,那么 move
他们就在那里:
fn main() {
let mut arr = Vec::with_capacity(5);
for (i, chr) in "abcde".char_indices() {
arr.push(chr.to_string().repeat(3));
}
}
如果您绝对需要 &str
的数组,您仍然需要维护这些值 'alive' 至少与引用本身一样长:
fn i_only_consume_refs(data: Vec<&String>) -> () {}
fn main() {
let mut arr = Vec::with_capacity(5);
for (i, chr) in "abcde".char_indices() {
arr.push(chr.to_string().repeat(3));
}
let refs = arr.iter().collect();
i_only_consume_refs(refs)
}
在这里,我们仍然将所有创建的 String
移动到向量 arr
,然后引用其元素。这样,只要 arr
(谁拥有字符串),引用向量就有效。
TL;DR:有人需要拥有这些 String
,而您保留对它们的引用。你不能创建临时字符串,只存储引用,否则你将引用一个被丢弃的值,这确实很糟糕,编译器不会让你这样做。
现在我正在编写一个程序,我正在使用基于 for 循环中的条件构造的字符串更新 Vec
。我正在尝试做的(非常人为的)简化形式如下:
fn main() {
let mut arr = vec!["_"; 5];
for (i, chr) in "abcde".char_indices() {
arr[i] = &chr.to_string().repeat(3);
}
}
但是,我收到错误 temporary value dropped while borrowed
。关于在这里做什么的任何指示?
问题是arr
只持有引用,里面的字符串必须在别处拥有。一个可能的解决方法是简单地泄漏您在循环中创建的瞬态字符串。
fn main() {
let mut arr = vec!["_"; 5];
for (i, chr) in "abcde".char_indices() {
arr[i] = Box::leak(Box::new(chr.to_string().repeat(3)));
}
}
arr
的生命周期是main
方法的范围,而chr.to_string()
只在for循环体中有效。分配它会导致错误。
您可以使用 Vec<String>
而不是 Vec<&str>
来避免此问题。
fn main() {
let mut arr = vec!["_".to_string(); 5];
for (i, chr) in "abcde".char_indices() {
arr[i] = chr.to_string().repeat(3);
}
}
这里我们看到 String "_".to_string()
被复制了五次(效率不高)。我怀疑您的真实代码并非如此。
使用字符串也尝试 this 一个衬里:
let arr: Vec<String> = "abcde".chars().map(|c| c.to_string().repeat(3)).collect();
输出:
["aaa", "bbb", "ccc", "ddd", "eee"]
正如其他人所提到的,您正在创建的 String
必须 由某人拥有,否则它们最终会被丢弃。当编译器检测到这种删除发生时您的数组仍然保留对它们的引用,它会抱怨。
你需要考虑谁需要拥有这些价值。如果您最终的阵列是他们居住的自然场所,那么 move
他们就在那里:
fn main() {
let mut arr = Vec::with_capacity(5);
for (i, chr) in "abcde".char_indices() {
arr.push(chr.to_string().repeat(3));
}
}
如果您绝对需要 &str
的数组,您仍然需要维护这些值 'alive' 至少与引用本身一样长:
fn i_only_consume_refs(data: Vec<&String>) -> () {}
fn main() {
let mut arr = Vec::with_capacity(5);
for (i, chr) in "abcde".char_indices() {
arr.push(chr.to_string().repeat(3));
}
let refs = arr.iter().collect();
i_only_consume_refs(refs)
}
在这里,我们仍然将所有创建的 String
移动到向量 arr
,然后引用其元素。这样,只要 arr
(谁拥有字符串),引用向量就有效。
TL;DR:有人需要拥有这些 String
,而您保留对它们的引用。你不能创建临时字符串,只存储引用,否则你将引用一个被丢弃的值,这确实很糟糕,编译器不会让你这样做。