gpt4 book ai didi

vector - 在向量中存储 C++ std::function 的 Rust 等价物是什么?

转载 作者:行者123 更新时间:2023-11-29 08:04:33 25 4
gpt4 key购买 nike

这是我试图实现的 C++ 等价物:

std::vector<std::function<int(int)>> funcs;
funcs.emplace_back([](int n) -> int { return n + 1; });
int result = funcs[0](33);

如何用 Rust 编写上面的代码?

最佳答案

如果您不打算特别将函数移动到任何地方,您可以让类型推断在代码块中为您完成工作,并且完全按照字面定义您的闭包,就像它是一个普通变量一样(实际上,它是 - 它实现 FnFnMut):

let my_lambda = |n| n+1;
println!("{}", my_lambda(33));

Playground

如果您打算将此 lambda 移出堆栈,则需要将其装箱:

let my_lambda: Box<dyn Fn(u32) -> u32> = Box::new(|n| n + 1);
println!("{}", my_lambda(33));

Playground

这里的原理保持不变,唯一真正的区别是 lambda 现在在堆上。

然后将它们存储在 Vec 中变得相对简单,因为到目前为止我们已经证明它们是“正常”类型。没有什么能阻止您创建闭包向量,但您需要将它们装箱(Vec 要求每个元素都为 Sized,并且无法针对两个不同的闭包通过签名),他们将需要具有相同的签名:

let my_vector: Vec<Box<dyn Fn(u16) -> u16>> = vec![
Box::new(|i| i + 1),
Box::new(|i| i - 1),
];
println!("{}", my_vector[0](33))

如果它们有不同的签名,您将需要编写自己的结构来包含它们并按签名对它们进行存储,这不是一项简单的任务。


基准案例:

  • C++:

    #include <vector>
    #include <iostream>
    #include <functional>
    int main(int argc, char **argv) {
    std::vector<std::function<int(int)>> funcs;
    for (int i = 0; i < 10000000; i++) {
    funcs.push_back([&] (int n) { return n + 1; });
    int result = funcs[i](33);
    }
    }
  • 使用rust :

    fn main() {
    let mut lambdas:Vec<Box<Fn(u32) -> u32>> = vec![];
    for i in 0..10000000 {
    lambdas.push(Box::new(|i| i+1));
    lambdas[i](3);
    }
    }

编译选项:

  • G++: -O3 --std=c++0x
  • cargo :--release

结果:

  • C++ 峰值堆大小:

    --------------------------------------------------------------------------------
    n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B)
    --------------------------------------------------------------------------------
    68 383,911,899 268,512,208 268,508,160 4,048 0
    69 555,878,425 805,387,160 805,379,072 8,088 0
    70 765,593,697 805,387,160 805,379,072 8,088 0
  • Rust 峰值堆大小:

    --------------------------------------------------------------------------------
    n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B)
    --------------------------------------------------------------------------------
    46 210,486,321 268,440,920 268,436,765 4,155 0
    47 210,486,371 268,440,976 268,436,805 4,171 0
    48 210,486,496 268,441,064 268,436,885 4,179 0

结论:

  • C++ std::function 包装器是堆分配的。它包含的原始 lambda 本身是堆栈分配的,这种行为与 Rust 一致
  • Rust 更擅长内存优化,占用的堆大小是 C++ 的三分之一
  • Rust 在原始时间方面也更快

关于vector - 在向量中存储 C++ std::function 的 Rust 等价物是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58070894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com