编译器通过堆栈指针通过引用捕获是合法的。有一个轻微的缺点(因为必须将偏移量添加到所述堆栈指针)。
在包含缺陷的当前 C++ 标准下,您还必须通过伪指针捕获引用变量,因为绑定的生命周期必须与引用的数据一样长,而不是直接绑定到的引用。
更简单的实现,其中每个捕获的变量对应于构造函数参数和类成员变量,具有与“更正常”的 C++ 代码对齐的严重优势。需要做一些魔术this
工作,但除此之外,lambda 闭包是一个带有 inline 的沼泽标准对象实例operator()
。“更正常”的 C++ 代码的优化策略将起作用,错误将与“更正常”的代码大部分相同,等等。
如果编译器编写者使用堆栈帧实现,那么该实现中引用的引用捕获可能无法像在所有其他编译器中那样工作。当缺陷被解决(有利于它工作)时,代码将不得不再次更改。从本质上讲,使用更简单实现的编译器几乎肯定会比使用花哨实现的编译器有更少的错误和更多的工作代码。
使用堆栈帧捕获,必须针对该 lambda 定制所有针对 lambda 的优化。它相当于一个捕获 a 的类,对其进行void*
指针运算,并将结果数据转换为类型化指针。这将非常难以优化,因为指针算术倾向于块优化,尤其是堆栈变量之间的指针算术(通常是未定义的)。更糟糕的是,这种指针算法意味着堆栈变量状态的优化(消除变量、重叠生命周期、寄存器)现在必须以纠缠的方式与 lambdas 的优化交互。
进行这样的优化将是一件好事。作为奖励,因为 lambda 类型与编译单元相关联,弄乱 lambda 的实现不会破坏编译单元之间的二进制兼容性。因此,一旦它们被证明是稳定的改进,您就可以相对安全地进行此类更改。但是,如果您确实实施了该优化,您真的会希望能够恢复到更简单的经过验证的优化。
我鼓励你为你最喜欢的开源编译器提供补丁来添加这个功能。