Vec<&&str> 和 Vec<&Str> 一样吗?
Is Vec<&&str> the same as Vec<&Str>?
我正在学习 Rust,我正在尝试解决代码挑战(2015 年第 9 天)。
我创造了一种情况,我最终得到一个类型为 Vec<&&str>
的变量(请注意双“&”,这不是拼写错误)。我现在想知道这种类型是否与 Vec<&str>
不同。我无法弄清楚对某物的引用是否有意义。我知道我可以通过对 from
和 to
变量使用 String
来避免这种情况。我在问是否 Vec<&&str> == Vec<&str>
以及我是否应该尝试避免 Vec<&&str>
.
这里是触发这个问题的代码:
use itertools::Itertools
use std::collections::{HashSet};
fn main() {
let contents = fs::read_to_string("input.txt").unwrap();
let mut vertices: HashSet<&str> = HashSet::new();
for line in contents.lines() {
let data: Vec<&str> = line.split(" ").collect();
let from = data[0];
let to = data[2];
vertices.insert(from);
vertices.insert(to);
}
// `Vec<&&str>` originates from here
let permutations_iter = vertices.iter().permutations(vertices.len());
for perm in permutations_iter {
let length_trip = compute_length_of_trip(&perm);
}
}
fn compute_length_of_trip(trip: &Vec<&&str>) -> u32 {
...
}
你有 &&str
的原因是数据 &str
由顶点拥有,当你在该数据上创建一个 interator 时,你只是获得对该数据的引用,因此 &&str
.
这里真的没有什么可以避免的。它只是显示您的迭代器引用了 HashSet 中的数据。
Vec<&str> 和 Vec<&&str> 是不同类型吗?
I'm now wondering if this type is different than Vec<&str>
.
是的,Vec<&&str>
是不同于 Vec<&str>
的类型 - 您不能在需要 Vec<&str>
的地方传递 Vec<&&str>
,反之亦然。 Vec<&str>
存储字符串切片引用,您可以将其视为指向某些字符串内部数据的指针。 Vec<&&str>
存储对此类字符串切片引用的引用,即指向数据指针的指针。对于后者,访问字符串数据需要额外的间接访问。
然而,Rust 的自动取消引用使得 使用 成为可能 Vec<&&str>
就像你使用 Vec<&str>
- 例如,v[0].len()
在任何一个上都可以正常工作, v[some_idx].chars()
将用任何一个遍历字符,依此类推。唯一的区别是 Vec<&&str>
更间接地存储数据,因此每次访问都需要做更多的工作,这可能会导致代码效率稍低。
请注意,您始终可以将 Vec<&&str>
转换为 Vec<&str>
- 但由于这样做需要分配一个新向量,因此如果您决定不需要 Vec<&&str>
,则更好一开始就不要创建它。
我可以避免 Vec<&&str> 吗?如何避免?
由于 &str
是 Copy
,您可以通过在遍历 vertices
时添加 .copied()
来避免创建 Vec<&&str>
,即更改vertices.iter()
到 vertices.iter().copied()
。如果你不需要 vertices
坚持下去,你也可以使用 vertices.into_iter()
,它会在迭代完成后立即给出 &str
以及免费的 vertices
向量完成。
附加引用的产生原因及避免方法以前
我应该避免使用 Vec<&&str> 吗?
Vec<&&str>
本身并没有什么需要避免的错误。在大多数代码中,您永远不会注意到 Vec<&&str>
和 Vec<&str>
之间的效率差异。话虽如此,除了微基准测试的性能之外,还有一些原因可以避免它。 Vec<&&str>
中的附加间接需要确切的 &str
s 从中创建(而不仅仅是拥有数据的字符串)来保留并比新集合更有效。这与您的情况无关,但如果您想 return 对拥有字符串的调用者进行排列,这会变得很明显。此外,不在每个转换上累积引用的更简单类型也有其价值。试想一下需要将 Vec<&&str>
进一步转换为一个新的向量 - 你不想处理 Vec<&&&str>
,等等每个新的转换。
关于性能,较少的间接性通常更好,因为它避免了额外的内存访问并增加了数据局部性。但是,还应该注意 Vec<&str>
每个元素占用 16 个字节(在 64 位体系结构上),因为切片引用由“胖指针”表示,即 pointer/length 对。另一方面,Vec<&&str>
(以及 Vec<&&&str>
等)每个元素仅占用 8 个字节,因为对胖引用的引用由常规的“瘦”指针表示。因此,如果您的矢量测量数百万个元素,则 Vec<&&str>
可能比 Vec<&str>
更高效 ,因为它占用的内存更少。一如既往,如有疑问,请测量。
我正在学习 Rust,我正在尝试解决代码挑战(2015 年第 9 天)。
我创造了一种情况,我最终得到一个类型为 Vec<&&str>
的变量(请注意双“&”,这不是拼写错误)。我现在想知道这种类型是否与 Vec<&str>
不同。我无法弄清楚对某物的引用是否有意义。我知道我可以通过对 from
和 to
变量使用 String
来避免这种情况。我在问是否 Vec<&&str> == Vec<&str>
以及我是否应该尝试避免 Vec<&&str>
.
这里是触发这个问题的代码:
use itertools::Itertools
use std::collections::{HashSet};
fn main() {
let contents = fs::read_to_string("input.txt").unwrap();
let mut vertices: HashSet<&str> = HashSet::new();
for line in contents.lines() {
let data: Vec<&str> = line.split(" ").collect();
let from = data[0];
let to = data[2];
vertices.insert(from);
vertices.insert(to);
}
// `Vec<&&str>` originates from here
let permutations_iter = vertices.iter().permutations(vertices.len());
for perm in permutations_iter {
let length_trip = compute_length_of_trip(&perm);
}
}
fn compute_length_of_trip(trip: &Vec<&&str>) -> u32 {
...
}
你有 &&str
的原因是数据 &str
由顶点拥有,当你在该数据上创建一个 interator 时,你只是获得对该数据的引用,因此 &&str
.
这里真的没有什么可以避免的。它只是显示您的迭代器引用了 HashSet 中的数据。
Vec<&str> 和 Vec<&&str> 是不同类型吗?
I'm now wondering if this type is different than
Vec<&str>
.
是的,Vec<&&str>
是不同于 Vec<&str>
的类型 - 您不能在需要 Vec<&str>
的地方传递 Vec<&&str>
,反之亦然。 Vec<&str>
存储字符串切片引用,您可以将其视为指向某些字符串内部数据的指针。 Vec<&&str>
存储对此类字符串切片引用的引用,即指向数据指针的指针。对于后者,访问字符串数据需要额外的间接访问。
然而,Rust 的自动取消引用使得 使用 成为可能 Vec<&&str>
就像你使用 Vec<&str>
- 例如,v[0].len()
在任何一个上都可以正常工作, v[some_idx].chars()
将用任何一个遍历字符,依此类推。唯一的区别是 Vec<&&str>
更间接地存储数据,因此每次访问都需要做更多的工作,这可能会导致代码效率稍低。
请注意,您始终可以将 Vec<&&str>
转换为 Vec<&str>
- 但由于这样做需要分配一个新向量,因此如果您决定不需要 Vec<&&str>
,则更好一开始就不要创建它。
我可以避免 Vec<&&str> 吗?如何避免?
由于 &str
是 Copy
,您可以通过在遍历 vertices
时添加 .copied()
来避免创建 Vec<&&str>
,即更改vertices.iter()
到 vertices.iter().copied()
。如果你不需要 vertices
坚持下去,你也可以使用 vertices.into_iter()
,它会在迭代完成后立即给出 &str
以及免费的 vertices
向量完成。
附加引用的产生原因及避免方法以前
我应该避免使用 Vec<&&str> 吗?
Vec<&&str>
本身并没有什么需要避免的错误。在大多数代码中,您永远不会注意到 Vec<&&str>
和 Vec<&str>
之间的效率差异。话虽如此,除了微基准测试的性能之外,还有一些原因可以避免它。 Vec<&&str>
中的附加间接需要确切的 &str
s 从中创建(而不仅仅是拥有数据的字符串)来保留并比新集合更有效。这与您的情况无关,但如果您想 return 对拥有字符串的调用者进行排列,这会变得很明显。此外,不在每个转换上累积引用的更简单类型也有其价值。试想一下需要将 Vec<&&str>
进一步转换为一个新的向量 - 你不想处理 Vec<&&&str>
,等等每个新的转换。
关于性能,较少的间接性通常更好,因为它避免了额外的内存访问并增加了数据局部性。但是,还应该注意 Vec<&str>
每个元素占用 16 个字节(在 64 位体系结构上),因为切片引用由“胖指针”表示,即 pointer/length 对。另一方面,Vec<&&str>
(以及 Vec<&&&str>
等)每个元素仅占用 8 个字节,因为对胖引用的引用由常规的“瘦”指针表示。因此,如果您的矢量测量数百万个元素,则 Vec<&&str>
可能比 Vec<&str>
更高效 ,因为它占用的内存更少。一如既往,如有疑问,请测量。