const static auto lambda 与引用捕获一起使用
const static auto lambda used with capture by reference
在 C++11 函数中使用一些本地 lambda 对象时,我很想将它们声明为 const static auto lambda = ...
只是为了让编译器知道只需要一个 std::function
对象(并且可能优化调用 and/or 内联它)但我意识到在这种情况下通过引用捕获本地值会导致奇怪的行为。
考虑以下代码:
void process(const Data& data, const std::function<void(DataElement&>& lambda) {
...
}
void SomeClass::doSomething()
{
int foo = 0;
const static auto lambda = [&foo] () { .... ++foo; .... }
process(data, lambda);
}
这不适用于 doSomething()
的多次调用,但机制尚不清楚。
foo
是否在第一次调用时绑定,然后一直绑定到一个堆栈地址,该地址在连续调用时变得无效?
- 在这种情况下,我是不是被迫放弃了
static
?
标准中在哪里规定了这种行为?考虑到它是一个 static
变量,它在哪里构造?懒惰地第一次调用 doSomething()
(以便第一次调用有效)或在程序启动时?
当控制流第一次到达它的声明时,静态函数作用域变量被初始化 "lazily,"。这意味着通过引用捕获确实绑定到当前在堆栈上的 foo
,并且当调用终止时,该绑定变为悬空。
不要试图帮助编译器太多;使 lambda
static
看起来像是一个微优化,具有非常糟糕的副作用。实际创建闭包对象几乎没有任何开销,编译器可以轻松地将其内联,无论它是否为 static
。
更不用说即使使用您的方法,您也没有节省创建 std::function
对象的费用。 lambda 表达式的类型是一个未命名的闭包对象,notstd::function
。因此,即使 lambda
是 static
,无论如何都会在每次调用中创建 std::function
对象(除非整个对象都是内联的)。
This doesn't work with multiple invocations of doSomething()
but the mechanics is not clear.
这是因为foo
是在栈上分配的。 foo
的确切地址取决于导致调用 doSomething
的调用堆栈。换句话说,foo
的地址在函数调用之间很可能不同,除非调用堆栈完全相同。
在 C++11 函数中使用一些本地 lambda 对象时,我很想将它们声明为 const static auto lambda = ...
只是为了让编译器知道只需要一个 std::function
对象(并且可能优化调用 and/or 内联它)但我意识到在这种情况下通过引用捕获本地值会导致奇怪的行为。
考虑以下代码:
void process(const Data& data, const std::function<void(DataElement&>& lambda) {
...
}
void SomeClass::doSomething()
{
int foo = 0;
const static auto lambda = [&foo] () { .... ++foo; .... }
process(data, lambda);
}
这不适用于 doSomething()
的多次调用,但机制尚不清楚。
foo
是否在第一次调用时绑定,然后一直绑定到一个堆栈地址,该地址在连续调用时变得无效?- 在这种情况下,我是不是被迫放弃了
static
?
标准中在哪里规定了这种行为?考虑到它是一个 static
变量,它在哪里构造?懒惰地第一次调用 doSomething()
(以便第一次调用有效)或在程序启动时?
当控制流第一次到达它的声明时,静态函数作用域变量被初始化 "lazily,"。这意味着通过引用捕获确实绑定到当前在堆栈上的 foo
,并且当调用终止时,该绑定变为悬空。
不要试图帮助编译器太多;使 lambda
static
看起来像是一个微优化,具有非常糟糕的副作用。实际创建闭包对象几乎没有任何开销,编译器可以轻松地将其内联,无论它是否为 static
。
更不用说即使使用您的方法,您也没有节省创建 std::function
对象的费用。 lambda 表达式的类型是一个未命名的闭包对象,notstd::function
。因此,即使 lambda
是 static
,无论如何都会在每次调用中创建 std::function
对象(除非整个对象都是内联的)。
This doesn't work with multiple invocations of
doSomething()
but the mechanics is not clear.
这是因为foo
是在栈上分配的。 foo
的确切地址取决于导致调用 doSomething
的调用堆栈。换句话说,foo
的地址在函数调用之间很可能不同,除非调用堆栈完全相同。