You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中为何允许对临时值的数据成员执行赋值操作?

为什么这段Rust代码中的赋值操作是被允许的?

问题复现

首先看你给出的第一段可编译代码:

#[derive(Copy, Clone)]
pub struct X {
    pub a: u8,
}

fn main() {
    let x = X { a: 0 };
    { x }.a = 5;
    assert!(x.a == 5); // 断言可以通过,你之前预判的错误并不存在
}

你最初的疑问是:这里是不是在给临时值赋值?同时你发现下面两种写法无法通过编译:

({ x.a }) = 5;
let mut y: u8 = 0;
({ y }) = 5;

你提到自己曾在写unsafe代码时遇到相关困惑:为了缩窄unsafe块范围,你写了如下代码,一度以为这是bug:

unsafe { *some_struct }.mem1 = 5;

而没有选择你当时认为更稳妥的写法:

unsafe { *some_struct.mem1 = 5; }

核心原因:Rust的位置表达式与值表达式区分

Rust的表达式严格分为两类,这是理解这个行为的核心:

  • 位置表达式(Place Expression):代表一块真实存在的内存位置,有对应的内存地址,可以被写入、被借用,也就是常说的“左值”。
  • 值表达式(Value Expression):代表一个具体的值,可能是寄存器里的临时值、也可能是计算产生的中间结果,没有固定的可写入内存地址,也就是常说的“右值”,不能出现在赋值号左侧。

为什么{ x }.a = 5合法?

  1. 块表达式的语义规则:如果块的最后一个表达式是位置表达式,且块内没有对这个位置做移动、拷贝产生新值的操作,整个块表达式本身也是位置表达式,直接指向原表达式对应的内存位置,不会产生临时值。
    这里x是栈上X实例的绑定,本身是位置表达式;块{ x }没有任何额外操作,所以整个块是指向原x变量内存的位置表达式,不是临时拷贝。
  2. 对结构体的位置表达式做字段访问.a,得到的依然是位置表达式,指向结构体对应字段的内存地址。
  3. 赋值号左侧要求必须是位置表达式,因此这里的赋值直接修改原x的a字段,断言可以正常通过,不存在“给临时值赋值”的问题。

为什么后两种写法不合法?

这两种写法的块返回的都是值表达式,不符合赋值左值要求:

  • 对于({ x.a }) = 5:x.a是u8类型,实现了Copy trait。当它作为块的最后一个表达式时,上下文要求返回一个值,因此会触发拷贝,产生一个临时的u8值,整个块是值表达式,无法被赋值。
  • 对于({ y }) = 5:同理,y是实现了Copy的u8类型,块返回y时会自动拷贝出临时值,属于值表达式,不能放在赋值号左侧。

关于你提到的unsafe代码的误区

你当时写的unsafe { *some_struct }.mem1 = 5不仅不是bug,反而是完全正确的写法:

  1. 块表达式(包括unsafe块)的优先级高于字段访问运算符.,因此代码会先执行unsafe块内的*some_struct解引用操作,得到指向指针目标结构体的位置表达式,整个unsafe块返回这个位置,不会产生临时结构体拷贝。
  2. 后续的.mem1 = 5直接修改原结构体的对应字段,逻辑完全符合预期,同时把unsafe操作限制在了最小范围内,是非常规范的写法。

反而你当时想改成的unsafe { *some_struct.mem1 = 5; }才是有bug的写法:Rust中.运算符优先级高于解引用运算符*,这段代码实际等价于unsafe { *(some_struct.mem1) = 5; },也就是先访问some_struct的mem1字段再解引用,和你“先解引用结构体指针、再访问字段”的预期逻辑完全相反。

关键规则总结

  • 赋值号左侧必须是位置表达式,代表可写入的内存位置。
  • 块表达式的类型(位置/值)由最后一行表达式决定,只要最后一行是位置表达式且没有触发拷贝/移动,整个块就是位置表达式。
  • Copy类型在值上下文中会自动拷贝产生临时值,此时表达式从位置表达式转为值表达式。
  • 涉及指针解引用、字段访问的unsafe代码要特别注意运算符优先级:.优先级高于*,混写时要么用块包裹解引用操作(就是你最初的写法),要么手动加括号(*ptr).field明确优先级,不要为了缩窄unsafe块写出有逻辑错误的代码。

内容的提问来源于stack exchange,提问作者nicolai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:45:42