Aber der Border Checker sagt, dass die Zeichenfolge nicht lange genug lebt.
Das ist, weil es nicht ist. Sie verwenden den Iterator nicht, so dass die Art der digits
ist
std::iter::Map<std::str::Chars<'_>, <closure>>
Das heißt, ein noch-zu-sein-bewertet Iterator, die Verweise auf die zugewiesenen String (der nicht namentlich Lebensdauer '_
in Chars
) enthält. Da diese Zeichenfolge jedoch keinen Eigentümer hat, wird sie am Ende der Anweisung gelöscht. bevor der Iterator verbraucht ist.
Also, yay für Rust, es verhindert eine Verwendung-nach-Free-Bug!
Die Verwendung des Iterators würde das Problem "lösen", da die Verweise auf die zugewiesene Zeichenfolge nicht versuchen würden, länger als die zugewiesene Zeichenfolge zu leben. sie enden alle am Ende der Aussage:
let digits: Vec<_> = num.to_string().chars().map(|d| d.to_digit(10).unwrap()).collect();
Wie für eine alternative Lösung gibt es die math way, stolen from the C++ question:
fn x(n: usize) -> Vec<usize> {
fn x_inner(n: usize, xs: &mut Vec<usize>) {
if n >= 10 {
x_inner(n/10, xs);
}
xs.push(n % 10);
}
let mut xs = Vec::new();
x_inner(n, &mut xs);
xs
}
fn main() {
let num = 42;
let digits: Vec<_> = num.to_string().chars().map(|d| d.to_digit(10).unwrap()).collect();
println!("{:?}", digits);
let digits = x(42);
println!("{:?}", digits);
}
aber Sie können alle Sonderfall Logik hinzufügen möchten für negative Zahlen und Tests wären keine schlechte Idee.
Vielleicht wollen Sie auch eine Phantasie-Hosen Iterator Version:
struct Digits {
n: usize,
divisor: usize,
}
impl Digits {
fn new(n: usize) -> Self {
let mut divisor = 1;
while n >= divisor * 10 {
divisor *= 10;
}
Digits {
n: n,
divisor: divisor,
}
}
}
impl Iterator for Digits {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.divisor == 0 {
None
} else {
let v = Some(self.n/self.divisor);
self.n %= self.divisor;
self.divisor /= 10;
v
}
}
}
fn main() {
let digits: Vec<_> = Digits::new(42).collect();
println!("{:?}", digits);
}
Ich sehe nicht, wie das eine Verwendung nach freien Fehler werden würde. Würde es nicht sofort benutzt werden und DANN danach befreit? –
über das Hinzufügen spezieller Fall Tests für negative Zahlen: die Funktion, die dies verwendet 'u32', negative Zahlen werden nie passieren –
@ElectricCoffee: Die Verwendung-nach-Frei kommt, weil' to_string' schafft eine temporäre, die nur so lange lebt wie die Anweisung, in der es erstellt wurde. Allerdings lebt Ihr Iterator "digits", der sich auf dieses temporäre bezieht, wesentlich länger, was inkorrekt ist. Wenn Sie in derselben Anweisung sofort "collect" aufrufen, besteht kein Problem mehr. –