rust - 如何将 2D vec 作为切片传递给函数?
问题描述
对于一维,代码模型是:
fn main() {
let a = vec![1, 2, 3, 4, 5];
print_it(&a); // :)
}
fn print_it(p: &[usize]) {
println!("{:?}", p);
}
我尝试对二维向量应用等效逻辑,但它不起作用
fn main() {
let a: Vec<Vec<usize>> = vec![
vec![1,2,3,4,],
vec![5,6,7,8,],
];
print_it(&a); // :( expected slice `[&[usize]]`, found struct `Vec`
}
fn print_it(p: &[&[usize]] ) {
println!("{:?}", p);
}
我究竟做错了什么?
解决方案
如果没有额外的工作,这种转换是不可能的。来自切片类型的官方文档:
一个动态大小的视图到一个连续的序列中,[T]。此处的连续意味着元素的布局使得每个元素与其相邻元素的距离相同。
这意味着指向的内存看起来像这样:
| T | T | ... | T |
切片是表示为指针和长度的内存块的视图。
这意味着该类型[&[usize]]
在内存中可能看起来像这样:
| pointer, length | pointer, length | ... | pointer, length |
但是,您有一个向量向量。向量有一个指向其分配内存的指针和两个usize
s,一个用于长度,一个用于容量。因此A[Vec<T>]
是
| pointer, length, capacity | pointer, length, capacity | ... | pointer, length, capacity |
在其Vec<Vec<T>>
内部缓冲区中也有此布局。由于指针长度对的后一种布局不是连续的(容量空间在usize
中间),我们不能仅仅将指向该内存的指针重新解释为&[&[T]]
.
如果您真的需要 2D 切片,则必须分配一个具有指针长度布局的新缓冲区:
let v: Vec<Vec<usize>> = todo!();
let slice2d: Vec<&[usize]> = v.iter().map(Vec::as_slice).collect();
如果您只是不想将函数签名限制为Vec
,则可以使其更通用:
use std::ops::Index;
fn print_it<I>(p: &[I])
where
I: Index<usize, Output = usize>,
{
println!("{:?}", p[0][0]);
}
推荐阅读
- mysql - 尝试配置 CartoDB 时无法使用 db:create
- c# - 使用 C# 删除 Windows 用户(远程)
- javascript - 使用另一个 json 对象从 json 对象中删除特定内容
- three.js - 使用 InstancedBufferGeometry 时未定义索引
- javascript - 如何让particle.js 只移动一个特定的div?
- html - CSS:计算两个重叠矩形在旋转后的溢出
- c++ - 我可以安全地混合使用 -std=c++11 和 -std=c++14 编译的库吗?
- cmake - CMake 将项目文件夹移动到另一台计算机
- php - 在模型 PHP CI 中获取结果搜索
- python - 从字符串中获取特定信息