Pointers 在移动Vec时,我是否可以(不安全地)握住指向Vec元素的指针?

Pointers 在移动Vec时,我是否可以(不安全地)握住指向Vec元素的指针?,pointers,rust,move-semantics,unsafe,vec,Pointers,Rust,Move Semantics,Unsafe,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

我正在实现一个算法,为了保持所需的时间复杂度,我希望在移动
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 });
}
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 Stack Overflow without reading the surrounding prose 
    println!("{}", unsafe { *ptr });
}
fn main(){
让mut v:Vec=Vec![1,2,3];
让ptr:*mut usize=&mut v[1]作为*mut usize;
设mut u:Vec=v;
断言!(ptr==&mut u[1]为*mut usize);
println!(“{}”,不安全的{*ptr});
}
实际代码更为复杂,并且涉及一个树状数据结构,其中每个顶点都拥有一个子节点的
Vec
。这里我不是问编码风格,但我的问题是,是否可以依赖这些代码来完成我认为它所做的事情


由于
Vec
必须将其内容保存在堆上,而moves在Rust中相当于
memcpy
,因此我认为
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 });
}
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 Stack Overflow without reading the surrounding prose 
    println!("{}", unsafe { *ptr });
}
fn main(){
让mut v:Vec=Vec![1,2,3];
让ptr:*mut usize=&mut v[1]作为*mut usize;
设mut u:Vec=v;
断言!(ptr==&mut u[1]为*mut usize);
//我从Stack Overflow复制了这篇文章,没有阅读周围的散文
println!(“{}”,不安全的{*ptr});
}
您应该准确记录
不安全
块的安全条件以及维护安全条件的方式。在这种情况下

  • Vec
    的元素包括:

    如果
    Vec
    已分配内存,则它指向的内存位于堆上

  • 您在移动期间未更改支持分配。这可能是由于对
    Vec
    的任何修改导致调整大小或破坏

  • 尝试使用引用时,不存在对同一元素的别名引用(包括可能到达同一元素的任何内容)



  • 对于这个例子,我只使用一个索引(
    1
    )。对于您的树案例,我将尝试使用索引向量。基准测试以查看是否存在明显的差异。

    除非移动的向量的大小超出其容量(通过添加元素),否则在这种情况下,您会留下一个悬空指针(因为所有数据都复制到另一个容量更大的位置)
    Vec
    是否真的保证在任何情况下都能将其元素保留在堆上?它是否有可能被允许进行一些小的向量优化(例如,如果一个数组中只有4个元素,则保留元素)?@AlexLarionov我可以保证移动的向量的大小不会超过其容量。@Phimueme好的,
    Vec
    具有
    从原始部分
    到原始部分
    ,我认为如果存在小向量优化,它们是不可实现的。@PhimueMe Vec永远不会执行“小优化”,其中元素实际存储在堆栈()上,而在不安全块中,
    Vec
    本身和
    &mut usize
    将共存,编译器不会知道
    &mut usize
    来自
    Vec
    。一般来说,对
    u
    的mut引用与对
    u[1]
    的mut引用共存(只要我没有第二个对
    u[1]
    的引用)可以接受吗?
    u
    中没有任何引用,只有更多的原始指针。对
    u
    的可变引用是可疑的。您将能够获得该元素的第二个可变引用;对不起,我想我不清楚。我的意思是类似于。是的,在安全的情况下不可能做这样的事。但是,如果我想通过一个期望引用的API(根据链接的代码)来改变指针中的元素,会不会因为mut ref与
    u
    共存而立即变成UB?我可以通过执行
    &mutu[1]
    来获取另一个mut ref,我认为这将是立即的;但是如果我没有这样做,代码会保持良好的定义吗?正如我提到的,
    u
    中没有任何引用。因为它没有引用,所以不能与另一个引用混淆。