Могу ли я удерживать указатель (небезопасно) на элемент 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
блокировать с точными условиями безопасности и тем, как вы их поддерживаете. В этом случае...
В
Vec
элементы размещены в куче:Если
Vec
выделил память, то память, на которую он указывает, находится в кучеВы не изменили распределение резервных копий во время переезда. Это могло быть связано с любой модификацией
Vec
что приводит к изменению размера или уничтожению.Когда вы пытаетесь использовать ссылку, не существует ссылки на один и тот же элемент (включая все, что может достичь того же элемента).
В этом примере я бы просто использовал индекс (1
). Для вашего случая дерева я бы попытался использовать вектор индексов. Выполните тест, чтобы увидеть, есть ли заметная разница.