如何在Rust中进行高效的向量初始化?

5
有什么好的方法可以在Rust中填充一个结构体向量,满足以下条件:
- 大小是动态的,但在初始化时已知。 - 不需要先将内存初始化为虚拟值。 - 不需要在填充时重新分配内存。 - 在此示例中,向量的所有成员都始终被初始化(与Rust保证没有未定义行为相一致)。
而且最理想的情况是:
- 不需要对每个索引访问进行索引检查(因为在声明向量时已经知道了大小,这应该是可能的)。 - 不需要使用unsafe关键字(不确定是否合理,然而编译器可以检测到所有值始终被填充,从而允许在unsafe代码块中使用这样的逻辑)。
C等效代码如下:
struct MyStruct *create_mystruct(const uint n) {
    struct MyStruct *vector = malloc(sizeof(*vector) * n);
    for (uint i = 0; i < n; i++) {
        /* any kind of initialization */
        initialize_mystruct(&vector[i], i);
    }
    return vector;
}

我正在移植一些用C编写的代码,它使用一个简单的循环来填充数组,因此我想知道是否有一种Rustic方式来执行这样一个常见任务,并且没有或者只有最小的开销?

如果在Rust版本的代码中通常需要进行一些额外的检查,那么最接近的等价物是什么?


请参阅以下链接:https://dev59.com/nnrZa4cB1Zd3GeqP341A,https://dev59.com/1F8d5IYBdhLWcg3wNAGy,https://dev59.com/cV4c5IYBdhLWcg3w6N07,https://dev59.com/c14b5IYBdhLWcg3wzUja,https://dev59.com/ol0b5IYBdhLWcg3wLOc2,https://dev59.com/Il0Z5IYBdhLWcg3whApv。 - Shepmaster
检查了所有其他问题,不认为它们是直接重复的(尽管有些很接近)。 - ideasman42
1个回答

10

只需使用mapcollect

struct MyStruct(usize);

fn create_mystructs(n: usize) -> Vec<MyStruct> {
    (0..n).map(MyStruct).collect()
}

"初始化"在安全的 Rust 中没有意义,因为你需要访问未初始化的值,这是不安全的。当收集到容器时,可以使用Iterator::size_hint方法来确保最少的分配次数。

基本上,我相信优化器会处理正确的事情。如果它没有,我相信它最终会处理正确。


initialize_mystruct 应该放在哪里?此外,我假设 Rust 足够聪明,能够检测到迭代器具有固定大小,在运行 collect 时不会调整向量的大小? - ideasman42
1
@ideasman42,你应该使用MyStruct的构造函数而不是initialize_mystruct,然后执行.map(MyStruct::new)。Rust知道map保留长度并且会正确分配内存。 - Veedrac
而且由于我使用了一个元组结构体,所以MyStruct的构造函数只是MyStruct,在map中调用的函数。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接