Могу ли я удерживать указатель (небезопасно) на элемент Vec, пока Vec перемещается?

Я реализую алгоритм, и, чтобы поддерживать желаемую временную сложность, я хотел бы сохранить указатель на элемент Vec в то время как Vec перемещается.

Конкретно примерно так:

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3];
    let ptr: *mut usize = &mut v[1] as *mut usize;
    let mut u: Vec<usize> = v;
    assert!(ptr == &mut u[1] as *mut usize);
    println!("{}", unsafe { *ptr });
}

Фактический код более сложен и включает древовидную структуру данных, в которой каждой вершине принадлежит Vecдетей. Я не спрашиваю здесь о стиле кодирования, но мой вопрос в том, можно ли полагаться на этот код, чтобы делать то, что я думаю.

поскольку Vec должен хранить свое содержимое в куче, а ходы эквивалентны memcpy в Rust я думаю, что Vecявляется подвижным, означало бы, что мой код исправен (т.е. не имеет неопределенного поведения). Это правильно?

1 ответ

Сделать это можно так:

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3];
    let ptr: *mut usize = &mut v[1] as *mut usize;
    let mut u: Vec<usize> = v;
    assert!(ptr == &mut u[1] as *mut usize);
    // I copied this from stackru without reading the surrounding prose 
    println!("{}", unsafe { *ptr });
}

Вы должны задокументировать unsafeблокировать с точными условиями безопасности и тем, как вы их поддерживаете. В этом случае...

  1. В Vecэлементы размещены в куче:

    Если Vec выделил память, то память, на которую он указывает, находится в куче

  2. Вы не изменили распределение резервных копий во время переезда. Это могло быть связано с любой модификациейVec что приводит к изменению размера или уничтожению.

  3. Когда вы пытаетесь использовать ссылку, не существует ссылки на один и тот же элемент (включая все, что может достичь того же элемента).


В этом примере я бы просто использовал индекс (1). Для вашего случая дерева я бы попытался использовать вектор индексов. Выполните тест, чтобы увидеть, есть ли заметная разница.

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