微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当你在 Rust 中可变地阴影一个 Vector 时会发生什么?

如何解决当你在 Rust 中可变地阴影一个 Vector 时会发生什么?

我目前正在学习 rustlings 课程,当这个关于 移动语义 的练习出现时,我感到很困惑。这是它的要点:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.4</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>${spring.boot.version}</version>
</dependency>

据我所知,不可变的 fn main(){ let vec0 = Vec::new(); let mut vec1 = fill_vec(vec0); //stuff happens } fn fill_vec(vec: Vec<i32>) -> Vec<i32> { let mut vec = vec; //do stuff vec } 正在作为参数 vec0 移动到 fill_vec,然后由 {{1} 可变地隐藏 }}。由于 Vector 是对堆存储的引用,这是否意味着 vec 由于阴影而发生,还是相同的指针被重用并且只是可变?为什么要在这种情况下使用阴影?

解决方法

是否重复使用了相同的指针并使其可变?

是的。完全相同的对象,在运行时它本质上是一个空操作。

为什么要在这种情况下使用阴影?

有些人喜欢通过阴影临时“锁定”和“解锁”绑定的模式,例如

let a = …;
…
let mut a = a;
// mutate `a` in-place
let a = a; // lock to readonly again

这真的只是个人喜好。这里:

  • 本可以引入一个新变量,但它真的会更有用吗?会叫什么? vec_mut?不像源可以重复使用,它被移走了。
  • 或者,输入参数可以直接为 mut vec: …

这主要取决于个人选择。

,

从语义上讲,它是同一个对象,只是在您的情况下更改了名称。

但在当前实现中,它会将您的堆栈数据复制到堆栈中的新位置,因此 Vec 对象的地址将更改(但堆指针保持不变)。 这样做是因为你可以用新对象隐藏旧名称:

let v = make_first_vec();
let mut v = make_second_vec();
// old v still exists and it would be dropped only at end of block.

更好的例子(你可以运行它):

struct Droppable(i32);

impl Drop for Droppable{
    fn drop(&mut self){
        println!("Dropping {}",self.0);
    }
}

fn main(){
    // Same object moved
    // Changes stack location but still same object
    // dropped only once
    println!("Same object moved begin");
    {
        let a = Droppable(1);
        let old_ref = &a;
        println!("Address is {}",&a as *const _ as usize);
        let mut a = a;
        println!("Address is {}",&a as *const _ as usize);
        let a = a;
        println!("Address is {}",&a as *const _ as usize);
        // Cannot use old reference because old object is moved
        // Compile error if uncommented
        // println!("Old object is still alive and has {}",old_ref.0);
    }
    println!("Same object moved end");
    
    // Different object hides
    // dropped in reverse order
    println!("Different object hides begin");
    {
        let a = Droppable(2);
        let old_ref = &a;
        println!("Address is {}",&a as *const _ as usize);
        let a = Droppable(3);
        println!("Address is {}",&a as *const _ as usize);
        println!("Old object is still alive and has {}",old_ref.0);
    }
    println!("Different object hides end");
    
    // Different object overrides
    // old object dropped when overrided
    println!("Different object override begin");
    {
        let mut a = Droppable(4);
        let old_ref = &a;
        println!("Address is {}",&a as *const _ as usize);
        a = Droppable(5);
        println!("Address is same {}",&a as *const _ as usize);
        // Cannot use old reference because old object destroyed
        // Compile error if uncommented
        // println!("Old object is still alive and has {}",old_ref.0);
    }
    println!("Different object override end");
}

它打印:

Same object moved begin
Address is 140736088967924
Address is 140736088967888
Address is 140736088967892
Dropping 1
Same object moved end
Different object hides begin
Address is 140736088967888
Address is 140736088967892
Old object is still alive and has 2
Dropping 3
Dropping 2
Different object hides end
Different object override begin
Address is 140736088967892
Dropping 4
Address is same 140736088967892
Dropping 5
Different object override end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。