为什么允许以下代码片段中的分配?
#[derive(Copy, Clone)]
pub struct X {
pub a: u8,
}
fn main() {
let x = X { a: 0 };
{ x }.a = 5;
assert!(x.a == 5); // I was wrong
}
Run Code Online (Sandbox Code Playgroud)
我分配给临时工吗?
尽管这些是被禁止的:
({ x.a }) = 5;
let mut y: u8 = 0;
({ y }) = 5;
Run Code Online (Sandbox Code Playgroud)
我问,因为我有一个像这样的错误
unsafe { *some_struct }.mem1 = 5;
Run Code Online (Sandbox Code Playgroud)
我没用过
unsafe { *some_struct.mem1 = 5; }
Run Code Online (Sandbox Code Playgroud)
从一开始,因为让不安全块尽可能短感觉是正确的。
是的,您正在分配给临时对象,因为 X 实现了 Copy,因此{ x }您正在创建一个返回 x 的块,但 X 实现了 Copy,因此您的块返回 x 的副本。你的块基本上是这样的:
#[derive(Copy, Clone)]
pub struct X {
pub a: u8,
}
fn main() {
let x = X { a: 0 };
let mut tmp = { x };
tmp.a = 5;
assert_eq(x.a, 0);
assert_eq!(tmp.a, 5);
}
Run Code Online (Sandbox Code Playgroud)
要使块返回实际变量而不是副本,您可以做的是将指针转换为可变引用,并从不安全块返回该引用:
#[derive(Copy, Clone)]
pub struct X {
pub a: u8,
}
fn main() {
let mut x = X { a: 0 };
let ptr: *mut X = &mut x;
unsafe {
&mut *ptr
}.a = 5;
assert_eq!(x.a, 5);
}
Run Code Online (Sandbox Code Playgroud)
为什么允许?这是允许的,因为 Rust 允许你修改临时变量,否则很多事情会非常冗长,比如:
fn get_first<T>(vec: Vec<T>) -> Option<T> {
let first = vec.into_iter().next();
// ^ temporary iterator
first
}
Run Code Online (Sandbox Code Playgroud)
next()需要迭代器的可变引用。必须将其绑定到可变变量意味着您必须编写:
fn get_first<T>(vec: Vec<T>) -> Option<T> {
let mut iter = vec.into_iter();
let first = iter.next();
first
}
Run Code Online (Sandbox Code Playgroud)
您提供的禁止代码片段不满足编译器的要求,因为您尝试将一个值分配给另一个值,而不是变量:这样做{ var }会创建一个返回变量中的值的块,因此:
fn get_first<T>(vec: Vec<T>) -> Option<T> {
let mut iter = vec.into_iter();
let first = iter.next();
first
}
Run Code Online (Sandbox Code Playgroud)
您可以使用这个临时文件,但不能覆盖它,这是有意为之的,也是一件好事。我认为在 C++ 中,他们称之为左值和右值,块返回右值,并且不能分配给右值。
但是,是的,编译器不会将其视为{ x }.a临时的,这有点愚蠢,没有我能想到的用例,并且可能会造成混乱。
| 归档时间: |
|
| 查看次数: |
232 次 |
| 最近记录: |