fn test<T>(t: T) {
println!("size of: {}", std::mem::size_of::<T>());
}
fn main() {
let f = || {
let i1: i32 = 0;
let i2: i32 = 0;
let i3: i32 = 0;
i1 + i2 + i3
};
test(f) // prints "size of: 0"
}
非移动闭包似乎总是打印尺寸为0,可能是因为它只是内联。
移动闭包随着它捕获的每个变量变大,但我想知道是否有可能查询闭包所需的堆栈空间?
更新
我想创建像Coroutine<F>
这样的东西。我需要知道F
的大小才能执行它。我目前为每个协程分配1mb这太多了。所以我想知道是否有可能确定我需要分配的实际大小。
答案 0 :(得分:3)
我误解了这个问题,所以下面的文字并没有真正回答OP的问题!
是,您可以衡量一个闭包的大小。有时候尺寸有点混乱。让我们测试各种闭包:
let constant = || 27;
let no_capture = |x: i32| 27 + x;
let a = vec![3];
let immut_capture = || a[0] + 27;
let immut_capture_arg = |x: i32| a[0] + x;
let mut b = vec![3];
let mut c = vec![3];
let mut_capture = || { b[0] += 27; b[0] };
let mut_capture_arg = |x: i32| { c[0] += x; c[0] };
let mut d = vec![3];
let mut e = vec![3];
let move_capture = move || { d[0] += 27; d.into_boxed_slice() };
let move_capture_arg = move |x: i32| { e[0] += x; e.into_boxed_slice() };
当我使用std::mem::size_of_val
打印尺码时(大致相当于您手写的test()
功能),我得到以下结果:
constant -> 0
no_capture -> 0
immut_capture -> 8
immut_capture_arg -> 8
mut_capture -> 8
mut_capture_arg -> 8
move_capture -> 24
move_capture_arg -> 24
您可以使用this code on playground自行尝试。
闭包是一种通过引用或值来保存其环境的类型。对大小数据的可变和不可变引用具有相同的大小,即size_of::<usize>()
,通常为8.这解释了通过引用捕获外部变量的闭包的大小。
size_of::<Vec<_>>()
毫不奇怪。
大小为0的闭包怎么样?由于它们没有捕获任何环境,因此它们也可以是普通的fn
函数。我猜Rust会把它们变成fn
- 函数。事实上,如果我们尝试打印fn
项的大小(不是函数指针!),就像这样:
fn foo(x: i32) -> i32 { x + 27 }
println!("{}", std::mem::size_of_val(&foo));
...我们得到0!