Por que não consigo ler linhas de stdin, remover espaços em branco e colocá-los em um vetor? `line` não vive o suficiente [duplicado]

Aug 17 2020

Gostaria de ler linhas de stdin, remover espaços em branco e colocá-los em um vetor, mas não posso porque linenão vive o suficiente. Por quê?

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut read = Vec::new();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let line = line.trim();
        read.push(line);
    }
}
error[E0597]: `line` does not live long enough
  --> src/main.rs:8:20
   |
8  |         let line = line.trim();
   |                    ^^^^ borrowed value does not live long enough
9  |         read.push(line);
   |         ---- borrow later used here
10 |     }
   |     - `line` dropped here while still borrowed

Respostas

2 rodrigo Aug 17 2020 at 15:39

Se você olhar a definição de str::trim()(anotações vitalícias adicionadas):

pub fn trim<'a>(&'a self) -> &'a str

Você pode ver que ele retorna uma fatia da string que se refere a parte da string original. Ou seja, ele pega emprestado a string em vez de copiá-la. O que faz sentido, porque o resultado do trimé sempre uma substring do original.

Você pode se confundir com outras funções, como str::to_uppercase(),, que retornam um novo String. Obviamente, isso ocorre porque eles não retornam uma substring da string original, portanto, eles precisam criar uma nova.

TL; DR; Você pegou um emprestado, &strmas deseja um de sua propriedade Stringpara armazenar em seu Vec. Basta adicionar .to_string().

Sobre as desvantagens, ele vai alocar um novo String. Você poderia tentar evitá-lo fazendo um trimno local , mas não acho que vale a pena, a menos que você crie um perfil e decida que o corte está prejudicando seu desempenho.