基于 Rust 的 Vec
容器,可以表达数学里的 n 维点。下面的 foo
函数可以根据两个 n 维点 a 和 b,构造一个点集 {a, b, c},其中 c 是 a 和 b 的中点。
fn foo(a: &Vec, b: &Vec) -> Vec> {
assert_eq!(a.len(), b.len());
let mut c: Vec = Vec::new();
for i in 0 .. a.len() {
c.push(0.5 * (a[i] + b[i]));
}
let mut points: Vec> = Vec::new();
points.push(a.clone());
points.push(b.clone());
points.push(c);
return points;
}
注意,
points
存储的是 a
和 b
的副本,并非 a
和 b
本身。倘若我希望 points
里存储的是 a
和 b
本身,该如何做呢?我能想到的方案是fn foo(a: &Vec, b: &Vec) -> Vec<&Vec> {
assert_eq!(a.len(), b.len());
let mut c: Vec = Vec::new();
for i in 0 .. a.len() {
c.push(0.5 * (a[i] + b[i]));
}
let mut points: Vec<&Vec> = Vec::new();
points.push(a);
points.push(b);
points.push(&c);
return points;
}
现在,
points
存储的是 a
,b
和 c
的引用,但是 rustc 在编译这段代码时,会报错并指出,这个函数的返回值包含了一个借用值,但是函数签名却未能指明借用的是 a
还是 b
。虽然代码写的很明白,a
和 b
都被借用了,但即便如此,rustc 依然无法确定在 points
生命周期之内 a
和 b
是否仍然健在,因此需要通过生命周期标记告诉 rustc,a
以及 b
的生命周期至少与 points
一样长,亦即fn foo<'a>(a: &'a Vec, b: &'a Vec) -> Vec<&'a Vec> {
... ... ...
}
真正致命的问题在于
c
,即points.push(&c);
rustc 在编译这行代码时,会报错:
error[E0515]: cannot return value referencing local variable `c`
意思是,不能将一个局部变量的引用放在
points
里并将其返回。因为 foo
函数结束时,c
便寿终正寢,从而导致 points
对它的引用失效。我现在无法解决这个问题,只好乖乖地回到了最初的方案,用 points
存 a
和 b
所引用的点的副本,再存 c
。现在,再来写一个函数
bar
,用它修改 points
,将 c
放在 a
和 b
的中间:fn bar(points: &mut Vec>) {
let b = points[1];
points[1] = points[2];
points[2] = b;
}
逻辑上没问题,但是 rustc 认为,
move occurs because value has type `Vec`, which does not implement the `Copy` trait
意思就是
bar
里面的三条赋值语句,都是错的,原因是,Vec
没实现 Copy
Trait。要 Copy
什么呢?我只是希望 points
的第 2 个和第 3 个元素交换一下位置,并不想 Copy
什么啊。然而,我却不知道该怎样写这个函数了,倘若 points
存储的是引用,而不是实际的值,上述赋值语句应该是成立的,但是这又会导致 foo
函数难以定义。【与 Rust 勾心斗角 · 快没有爱了】感觉对 rust 快没有爱了……好在一开始就没有。
推荐阅读
- RUST与C/C++/Java/Go/Python应用领域比较
- Datenlord | Rust 语言无锁数据结构的内存管理
- 面试|【历史上的今天】5 月 15 日(Mozilla 发布 Rust;起点中文网成立;Windows 启动音乐设计者出生)
- ShowMeAI资讯日报|人工智能 | ShowMeAI资讯日报 #2022.06.16
- java面试题|Java面试题(2022全面复习java)
- 在2020 年,Rust 将会比 C++ 强在哪里()
- Rust|Windows 安装Rust
- Rust|Rust安装(windows)
- #|windows 配置中科大的 Rust 下载云,提高下载速度