【问题标题】:What are the semantics of mutably borrowing a literal in Rust? [duplicate]在 Rust 中可变地借用文字的语义是什么? [复制]
【发布时间】:2018-12-23 00:10:01
【问题描述】:

我发现这是可以编译的:

let x = &mut 10;
*x = 20;

这很令人困惑。可变借用字面量的语义是什么?

我来自 C++,编译器绝对不允许我像这样引用右值:

int *x = &10;
int &y = 10;

【问题讨论】:

  • @Boiethios 我不认为这是重复的。是有关系的,绝对的。但问题不同。
  • 有趣的是,在 C 中,#include <stdio.h> int main(void) { int *p = &(int){ 10 }; *p = 20; printf("%d", *p); } 是允许的。

标签: rust semantics literals borrowing


【解决方案1】:

与 C++ 一样,Rust 也有右值和左值的概念。引用将它们称为值表达式(右值)和位置表达式(左值)。此外,还有 value contextsplace contexts(表达式/语句中的插槽,分别需要值表达式或位置表达式)。

Rust 对值表达式(如文字)用于位置上下文(如借用运算符&)时有特殊规则。来自the reference

在大多数位置表达式上下文中使用值表达式时,会创建一个临时未命名的内存位置并初始化为该值,而表达式的计算结果会改为该位置 [...]。

所以 Rust 会自动将您的值 10 存储在内存位置。内存位置的生命周期取决于 如何 使用值表达式,但在您的情况下,未命名的内存位置与封闭块具有相同的生命周期。因此它相当于一个隐藏的let 绑定:

let _compiler_generated = 10;
let x = &mut _compiler_generated;
*x = 20;

这不仅仅适用于文字:

fn get_u32() -> u32 { 3 }

let x = &mut get_u32();
*x = 20;

虽然熟悉对象生命周期在 C++ 等语言中如何工作的人会感到困惑,但在某些情况下,这是一个相当有用的功能。


相关:如果您对文字使用 im可变引用,则该值不仅会写入堆栈槽,还会写入静态内存。这意味着let _: &'static u32 = &10 是有效的!这已在RC 1414 中指定。

【讨论】:

  • C++ 有时也会做类似的事情,尽管规则略有不同。
  • @Veedrac 我只能想到将 const 引用传递给函数时的特殊规则(然后在函数调用期间使引用持续存在)。还有更多规则吗?
  • const T &x = get_value(); 也得到扩展。据说const T &&x = get_value(); 也可以!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多