Rust: Tidak dapat membuat struktur yang menyimpan nilai dan referensi ke nilai-nilai ini [duplikat]

Saya membuat struktur yang menyimpan nilai dan referensi ke dalamnya, dan juga membuat metode untuk menambahkan nilai dan masa pakai tertentu. Contoh kode:

struct Storage<'a> {
    owner :Vec<i32>,
    links :Vec<&'a i32>
}

impl<'a> Storage<'a> {
    fn new() -> Storage<'a> {
        Storage {owner: vec![], links: vec![]}
    }

    fn add_int(&mut self, x :i32) {
        self.owner.push(x);
        let len = self.owner.len();
        let ref_x = match self.owner.get(len-1) {
            Some(x) => x,
            None => panic!("ERROR")
        };
        self.links.push(ref_x);
        let ref_x = 0;
    }
}

fn main() {
    let mut store = Storage::new();
    store.add_int(1);
    store.add_int(2);
}

Lalu saya mendapat kesalahan kompiler:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
let ref_x = match self.owner.get(len-1) {                                                               
                             ^^^         

Saya dapat memperbaiki kesalahan ini dan menetapkan untuk self seumur hidup 'a, untuk strukturnya. Namun dalam kasus ini self tidak akan dihapus bahkan setelah metode ini selesai. Dan kemudian ketika saya mencoba memanggil metode tersebut dua kali, saya mendapatkan kesalahan berikut:

error[E0499]: cannot borrow `store` as mutable more than once at a time

Namun bagaimana kontradiksi ini dapat diselesaikan?

Dan mungkin ada cara yang lebih tepat di Rust untuk menyimpan data dalam struktur dengan mengizinkan akses tidak hanya melalui pemiliknya?


person arcanius    schedule 03.01.2019    source sumber
comment
Secara teknis dimungkinkan untuk membuat struct yang meminjam sendiri dengan masa hidup, tetapi struct seperti itu tidak dapat dipindahkan (karena memindahkannya akan membatalkan referensi internal) dan tidak dapat dipinjam secara berubah-ubah (karena dipinjam secara permanen dan tidak dapat diubah), jadi tidak sering kali berguna untuk melakukannya. Cara terbaik untuk melanjutkan mungkin dengan membuat links menjadi Vec<usize> dan menyimpan indeks (yaitu daripada mengotak-atik ref_x, tulis saja self.links.push(len - 1)).   -  person trentcl    schedule 03.01.2019
comment
Terima kasih, trentcl.   -  person arcanius    schedule 03.01.2019
comment
Ini adalah contoh bagus dari Rust yang menyelamatkan kewarasan Anda. Di C++, kode Anda akan dikompilasi, dan diledakkan saat run-time. Masalah? Saat Anda menggunakan Vec::push, vektor mungkin kehabisan ruang (kapasitas penuh), dalam hal ini ia mengalokasikan larik baru (2x lebih besar), dan memindahkan semua elemen ke larik baru tersebut. Sayangnya, hal ini berarti tiba-tiba semua referensi (penunjuk) ke elemen tersebut menjadi menggantung: menunjuk ke memori yang kosong. Dan itulah Perilaku Tidak Terdefinisi, dan segala macam efek aneh bisa terjadi :x   -  person Matthieu M.    schedule 03.01.2019