解引用等同于函数调用吗?

3
如果我借用一个取消引用的指针会发生什么?
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;

发生错误。
1个回答

0

简短回答:这取决于情况。

详细回答:请继续阅读...

如果我借用了一个取消引用的指针会发生什么? 如果您查看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 决定是否自动创建一个可变的 box。在赋值的情况下,你的解引用 box 在赋值运算符的左侧,因此 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
}

1
你的答案是错误的:c 存储了 a 的别名。*b 不是栈临时变量,而是 a 的 rvalue 别名。可以通过一个简短的程序进行验证:http://is.gd/CLu5WQ - DK.
1
"c 借用了一个临时栈分配的对象",这真让我吃了一惊,于是我去查了一下。请参阅此处。这意味着不,c 借用了 a 而不是 a 的副本。否则就会相当令人困惑了。 - Vladimir Matveev
我忘记了右值引用:/ - oli_obk
在我的第二个问题中,我问为什么Box可以被改变而不需要类似于Box::new_mut(8us)这样的东西。 - Amos
@DK rvalue别名c是否借用了b? - Amos
@ker 是的。我对Box的解引用操作有了更深入的理解。但我仍然困惑于rvalue别名的变异。 - Amos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接