“&mut unsafe {}” 和 “unsafe { &mut }” 有什么区别?

9
我想将 *mut 指针转换为 &mut 引用。
// Both setting a value to ptr and getting a value from ptr succeeds.
let ptr: &mut usize = unsafe { &mut *(VIRTUAL_ADDRESS_TO_ACCESS_FREE_PAGE as *mut usize) };

这段代码是可行的。但是,如果&mutunsafe块之外,那么代码将无法完全工作。 *ptr = foo将不会将foo存储到指针ptr指向的内存中,但let foo = *ptr会将*ptr的值赋给foo

// Setting a value to ptr fails, but getting a value from ptr succeeds.
let ptr: &mut usize = &mut unsafe { *(VIRTUAL_ADDRESS_TO_ACCESS_FREE_PAGE as *mut usize) };

unsafe { &mut }&mut unsafe{ }有什么区别?

1个回答

11

这与unsafe本身没有关系,而是与块边界有关。

&*ptr是一种“reborrow”,它只是重新解释指针的新形式。因此,您可以获得对同一对象的不同类型的指针(一个原始指针和一个引用)。

&{*ptr}完全不同,因为{*ptr}强制复制[0] (感谢@harmic提供的来源):

块始终是值表达式,并在值表达式上下文中计算最后一个表达式。如果真的需要,这可以用于强制移动值。

然后它将借用该副本。这意味着您可以获得两个指向完全不同对象的指针。

对象具有相同的值,因为一个指向的对象是另一个对象的副本,因此读取似乎有效,但写入则无法正常工作,因为......您并非在您认为的位置进行写入。

请参见此演示(不使用mut指针,因为没有必要展示问题)


[0]更一般的是移动,但这里您指向的是Copy的usize


2
也许值得在这里添加一个链接(https://doc.rust-lang.org/stable/reference/expressions/block-expr.html),其中写道:“块始终是值表达式,并在值表达式上下文中评估最后一个表达式。如果确实需要,可以使用此方法来强制移动值。” - harmic

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