Rust: действительно ли `Box<T>` похож на `&'static T`?

Я могу понять, почему этот код не компилируется:

use std::{rc::{Rc, Weak}, cell::RefCell};

struct Container {
    list: Vec<Box<usize>>,
    this: Weak<RefCell<Self>>,
}

impl Container {
    fn new() -> Rc<RefCell<Self>> {
        let res = Rc::new(RefCell::new(Self {
            list: vec![],
            this: Weak::new(),
        }));

        {
            let this = Rc::downgrade(&res);
            let mut ref_on_res = res.borrow_mut();

            ref_on_res.this = this;
        }

        res
    }

    fn register(&mut self, v: usize) -> NumRef {
        let i = self.list.len();

        self.list.push(Box::new(v));

        NumRef::new(Weak::clone(&self.this), i)
    }

    fn get(&mut self, index: usize) -> &'static mut usize {
        let elt = &mut self.list[index];

        Box::as_mut(elt)
    }
}

struct NumRef {
    c: Weak<RefCell<Container>>,
    i: usize,
}

impl NumRef {
    fn new(c: Weak<RefCell<Container>>, i: usize) -> Self {
        Self { c, i }
    }

    fn get(&mut self) -> &'static mut usize {
        let c = self.c.upgrade().unwrap();

        c.borrow_mut().get(self.i)
    }
}

fn main() {
    let c = Container::new();
    let mut r = c.borrow_mut().register(1234);

    {
        let v = r.get();

        *v += 1;
    }

    {
        assert_eq!(c.borrow().list[0], Box::new(1235));
    }
}

Я могу понять, что &mut self.list[index] в строке 34 не переживет self.list.

Но в строке 26 Box::as_mut(elt) должна 'static причина жизни T жить в куче с Box<T>.

Компилятор говорит, что &mut self.list[index] должен жить до тех пор, пока Box::as_mut(elt), и я не понимаю, почему Box::as_mut(elt) является ссылкой на элемент, который находится в куче.

Где я ошибаюсь?

Ваша функция возвращает &mut usize, что не является коробочным значением. Вы также заимствуете у &'a self, чтобы вернуть &' static T, что не сработает, потому что тогда указатели не могут быть гарантированно действительными. Попробуйте вернуть Box<usize> и поискать BorrowMut в Vec.

MeetTitan 26.12.2020 00:24

Кроме того, чтобы ответить на ваш вопрос более прямо, поскольку Box может быть Dropped, вы не можете гарантировать, что ваш указатель указывает на ожидаемую память (после сброса память освобождается!).

MeetTitan 26.12.2020 00:29

Например: что произойдет, если Container удалит и отбросит значение, на которое у вас есть изменяемая ссылка? Это не может быть гарантировано 'static, потому что Container не 'static.

MeetTitan 26.12.2020 00:34
'static просто говорит: «Пока я в прицеле, мое указанное местоположение не изменится. Меня могут уронить, что сделает недействительным мое указанное воспоминание, но я не буду двигаться».
MeetTitan 26.12.2020 23:10

@MeetTitan, как Box, который выделен в куче, с указателем, который находится в куче и который не изменится (указатель не изменится).

Corebreaker 28.12.2020 11:20

Нет, не как коробка. Здесь не имеет значения, где выделена память. Я предлагаю прочитать о жизни. Время жизни — это не то, как долго «живет» память, время жизни — это то, как долго память «находится» по определенному адресу; так что вы можете предсказать и избежать висячих указателей во время компиляции.

MeetTitan 31.12.2020 17:56
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
6
305
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Box<T> действительно похож на &'static T?

Нет. Содержимое Box не обязательно живет в течение жизни программы, оно живет только до тех пор, пока существует Box, что часто намного короче.

Возврат &'static T из &mut self означает, что возвращаемая ссылка всегда действительна, но в данном случае это не так. Он связан с жизнью Box и, следовательно, с жизнью self.

fn get(&mut self, index: usize) -> &mut usize { ...

или с явно аннотированным временем жизни:

fn get<'a>(&'a mut self, index: usize) -> &'a mut usize { ...

Другие вопросы по теме