Rust书籍解释了如何使用struct update syntax创建一个只更新了几个字段的结构副本。
let mut point = Point3d { x: 0, y: 0, z: 0 };
point = Point3d { y: 1, .. point };
它也不必是相同的结构,在创建新结构时可以使用这种语法。
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { y: 1, .. origin };
我的问题是关于第二个例子。
如果永远不再使用origin
点,编译器是否仍会使(几乎)所有字段的副本(如果字段很大)或者只更新更新字段到位并等同于第一个示例?
如果它到位更新:编译器如何确定它是否可以覆盖origin
值?
答案 0 :(得分:5)
要回答诸如“编译器是否优化此问题?”之类的问题,我建议您查看反汇编。如果我在编译器资源管理器上编译并优化(-O
)以下内容:
pub struct P {
x: i32,
y: i32,
}
pub fn f() -> P {
let mut point = P { x: 43, y: 12 };
point = P { y: 1, ..point };
point
}
我明白了:
push rbp
mov rbp, rsp
movabs rax, 4294967339
pop rbp
ret
如果你知道一点装配,你可以看到没有创建或复制的中间变量。您可以为返回值的初始化添加额外的步骤,输出程序集不应更改。
如果删除优化(我不会在此处显示程序集),您可以在程序集中看到编译器生成第一个Point { x: 43, y: 12 }
,然后通过复制x
并初始化{{来创建一个新的y
。 1}}到1。
总结一下:
i32
)从第一个数据中创建一些数据来创建另一个点。答案 1 :(得分:1)
请注意,您正在链接到Rust书籍的第一个版本,特别是此时几乎<2年以上的版本。您的链接是1.6.0版的文档,但1.23.0是当前版本。 second edition of the book has different phrasing。
Rust书籍解释了如何使用struct update语法来创建struct
的副本
更新语法没什么特别之处。此示例代码仅创建副本,因为结构成员(在本例中为i32
)都实现了Copy
。
如果原点永远不会再次使用,编译器是否仍会复制[...]字段
这完全取决于结构的值是否实现Copy
:
#[derive(Debug)]
struct Coord;
#[derive(Debug)]
struct Point3d { x: Coord, y: Coord, z: Coord }
fn main() {
let origin = Point3d { x: Coord, y: Coord, z: Coord };
let point = Point3d { y: Coord, ..origin };
println!("{:?}", origin);
}
error[E0382]: use of partially moved value: `origin`
--> src/main.rs:15:22
|
13 | let point = Point3d { y: Coord, ..origin };
| ------ value moved here
14 |
15 | println!("{:?}", origin);
| ^^^^^^ value used here after move
|
= note: move occurs because `origin.x` has type `Coord`, which does not implement the `Copy` trait
除非实施Copy
,否则将移动值。 Copy
表示编译器可以随意复制类型的位:它没有副作用,这样做很有效,而且语义正确。
如果某个值被移动(即未实现Copy
),则之后您将无法使用它。
它也不必是相同的结构,在创建新结构时可以使用这种语法。
你 在这两种情况下都在制作一个新结构。碰巧的是,在第一种情况下,你碰巧有一个可变的绑定,你将它重新放入。它实际上相当于:
let point = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { y: 1, ..point };
答案 2 :(得分:0)
<强> YMMV 强> 1
一般来说,优化器的结果没有确定性。语言的语义可能会放置一些算法边界,但是,是否出现副本,单个副本或三个副本的程度取决于具体情况。
<强>语义强>
Rust 默认移动,因此如果源代码中没有.clone()
,则不会发生数据的深层复制。
另一方面,按位副本的数量未指定,可能会有所不同。
<强>优化强>
优化编译器(从那时起,优化器)在as-if规则下运行。每种语言都指定一组可观察行为,编译器必须生成与天真程序具有相同可观察行为的代码。可观察行为通常包括I / O,但忽略CPU周期和内存访问。
优化器有各种各样的技巧:
那么,你的案件会发生什么?的没有强>
由于您不是使用 Point
,因此它们不一定存在。
1 您的里程可能会发生变化,这是一个口语表达,意味着您的体验可能与其他人的体验不同,一般情况是因为您的情况略有不同。