我想要一些有关如何正确考虑C ++ 11闭包以及std::function
如何实现它们和如何处理内存的信息。
尽管我不相信过早的优化,但我确实有习惯在编写新代码时仔细考虑选择的性能影响。我还进行了大量的实时编程,例如在微控制器和音频系统上,以避免不确定的内存分配/重新分配暂停。
因此,我想更好地理解何时使用或不使用C ++ lambda。
我目前的理解是没有捕获的闭包的lambda就像C回调一样。但是,当通过值或引用捕获环境时,将在堆栈上创建一个匿名对象。当必须从函数返回值闭包时,将其包装在中std::function
。在这种情况下,关闭内存会发生什么?它是从堆栈复制到堆吗?每当释放时,std::function
就释放它std::shared_ptr
吗,也就是说,它是否像引用一样计数?
我想象在一个实时系统中,我可以建立一个lambda函数链,将B作为连续参数传递给A,从而A->B
创建处理管道。在这种情况下,A和B闭包将分配一次。虽然我不确定是将它们分配在堆栈还是堆上。但是总的来说,在实时系统中使用它似乎是安全的。另一方面,如果B构造了一些返回的lambda函数C,则C的内存将被重复分配和释放,这对于实时使用是不可接受的。
用伪代码,一个DSP循环,我认为它将是实时安全的。我要执行处理块A,然后执行B,其中A调用其参数。这两个函数都返回std::function
对象,因此f
将是一个std::function
对象,其环境存储在堆中:
auto f = A(B); // A returns a function which calls B
// Memory for the function returned by A is on the heap?
// Note that A and B may maintain a state
// via mutable value-closure!
for (t=0; t<1000; t++) {
y = f(t)
}
我认为在实时代码中可能不好用的一种:
for (t=0; t<1000; t++) {
y = A(B)(t);
}
我认为堆栈内存可能用于关闭的一种方式:
freq = 220;
A = 2;
for (t=0; t<1000; t++) {
y = [=](int t){ return sin(t*freq)*A; }
}
在后一种情况下,闭包是在循环的每次迭代中构造的,但与前面的示例不同,它很便宜,因为它就像一个函数调用一样,不进行堆分配。而且,我想知道编译器是否可以“解除”闭包并进行内联优化。
这样对吗?谢谢。
operator()
。没有要做的“提升”,lambda并没有什么特别的。它们只是局部函数对象的简写。