【问题标题】:Does dereference equal to a function call?取消引用是否等于函数调用?
【发布时间】:2015-02-03 13:43:46
【问题描述】:

如果我借用一个取消引用的指针会发生什么?

let a = some object;
let b = &a;
let c = &*b;

c 借用了什么对象?取消引用操作是否会创建一个临时对象,例如函数的返回值?它如何遵守借用规则。

我也对 Box 的可变语义感到困惑。

let mut a = Box::new(8us)
*a = 1;

没有像 Box::new_mut() 这样的代码可以正常工作。但是

let mut a = &8us;
*a = 1;

发生错误。

【问题讨论】:

    标签: rust


    【解决方案1】:

    快速回答:视情况而定。

    长答案:继续阅读...

    如果我借用一个取消引用的指针会发生什么? 如果您查看 rust 生成的 LLVM-IR,您可以详细查看所有内容:

    let a = 8us;
    let b = &a;
    let c = &*b;
    

    扩展为

    let a;
    // %a = alloca i64
    let b;
    // %b = alloca i64*
    let c;
    // %c = alloca i64*
    a = 8us;
    // store i64 8, i64* %a
    b = &a;
    // store i64* %a, i64** %b
    let tmp = *b;
    // %0 = load i64** %b
    c = tmp;
    // store i64* %0, i64** %c
    

    现在,llvm 可以轻松优化这些东西了。一旦你在自己的类型上实现了像Deref 这样的特征,它就会变得更加复杂。然后显然涉及一个函数调用,但很可能会再次优化,因为您不应该在 deref 函数中做复杂的事情。

    c 借用了什么对象?

    c借用a

    解引用操作是否会创建一个类似于函数返回值的临时对象?

    不,见上文

    它是如何遵守借用规则的。

    *b 的行为就像是 a。如果您引用它,您将获得对 a 的引用。


    回答你的第二个问题:

    Box 拥有它指向的对象。由于您将 Box 声明为可变的,因此您可以对对象进行可变引用或任意数量的非可变引用。这意味着当您取消引用 Box 时,rust 会根据情况决定是否自动创建一个可变框。在赋值的情况下,您的 deref'd 框位于赋值运算符的左侧,因此 rust 会尝试获取对该对象的可变引用。

    如果你给你的变量类型,这变得更加明显:

    let mut x = Box::new(8us);
    {
        let y : &usize = &*x;
    }
    {
        let y : &mut usize = &mut *x;
        *x = 99; // cannot assign to `*x` because it is borrowed
    }
    

    【讨论】:

    • 你的答案是错误的:c 存储了一个别名到a*b 不是临时堆栈,它是a 的右值别名。这可以通过一个简短的程序来验证:is.gd/CLu5WQ
    • "c 借用了一个临时堆栈分配的对象" 这真的让我很惊讶,我去看看。见here。这意味着不,c 借用了a,而不是a 的副本。否则会很混乱。
    • 我忘记了右值引用:/
    • 在我的第二期中,我问为什么 Box 可以在没有 Box::new_mut(8us); 之类的东西的情况下发生变异;
    • @DK 右值别名 c 是否借用 b?
    猜你喜欢
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    相关资源
    最近更新 更多