Как присваивание переменных со ссылками работает с ржавчиной, когда присваивание происходит внутри for l oop? - PullRequest
0 голосов
/ 07 августа 2020

Я только начал изучать ржавчину и еще не совсем понимаю систему ссылок, которую использует ржавчина. В следующей функции я пытаюсь написать код для FizzBuzz, который присваивает результату &str в зависимости от наименьшего общего кратного u32 в диапазоне.

fn fizzbuzz(last_num: u32) {
    for i in 1..last_num+1 {
        let result = if i % 15 == 0 {
            "FizzBuzz"
        } else if i % 3 == 0 {
            "Fizz"
        } else if i % 5 == 0 {
            "Buzz"
        } else {
            &i.to_string()[..]
        };
        println!("{}", result);
    }
}

в моем предложении else я получить следующую ошибку:

11 |           } else if i % 5 == 0 {
   |  ________________-
12 | |             "Buzz"
13 | |         } else {
14 | |             &i.to_string()[..]
   | |              ^^^^^^^^^^^^^ creates a temporary which is freed while still in use       
15 | |         };
   | |         -
   | |         |
   | |_________temporary value is freed at the end of this statement
   |           borrow later used here

Из того, что я до сих пор понимаю о ржавчине, это не должно быть проблемой, потому что ссылка &i используется до конца области, где i - освобождено из памяти.

Что именно я делаю не так и что исправить?

1 Ответ

0 голосов
/ 07 августа 2020

Проблема не в ссылке &i, а в создании чего-то нового в качестве временной переменной, которая имеет i.to_string() (тип String), а затем используется для создания str (примитивного типа), ссылающегося на тип String, который позже уничтожается, потому что это временно. Это означает, что вы называете что-то несуществующее. и String и str разные, вы можете увидеть объяснение здесь .

Самый простой способ исправить это - использовать вместо String:

fn fizzbuzz(last_num: u32) {
    for i in 1..last_num+1 {
        let result: String = if i % 15 == 0 {
            String::from("FizzBuzz")
        } else if i % 3 == 0 {
            String::from("Fizz")
        } else if i % 5 == 0 {
            String::from("Buzz")
        } else {
            i.to_string()
        };
        println!("{}", result);
    }
}

, но если вы хотите продолжать использовать тип str, вы можете сделать это, как показано ниже:

fn fizzbuzz(last_num: u32) {
    for i in 1..last_num+1 {
        let wont_be_destroyed: String = i.to_string(); 
        let mut result = &wont_be_destroyed[..];
        if i % 15 == 0 {
            result = &"FizzBuzz"
        } else if i % 3 == 0 {
            result = &"Fizz"
        } else if i % 5 == 0 {
            result = &"Buzz"
        }
        println!("{}", result);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...