Fle*_*exo 37 c++ lambda object-lifetime c++11
根据这个答案,我现在想知道lambda的生命周期是什么规则,以及与自动转换创建的函数指针的生命周期有什么关系.关于lambda的生命周期有几个问题(例如这里和这里),在这种情况下,答案是"它们的行为与你自己编写完整的仿函数对象完全一样",但是它们都没有解决转换为函数指针的问题.特殊情况.
我把这个小小的工作实例放在一起,说明了我的担忧:
#include <iostream>
typedef int (*func_t)(int);
// first case
func_t retFun1() {
static auto lambda = [](int) { return 1; };
// automatically converted to func_t
return lambda;
}
// second case
func_t retFun2() {
// no static
auto lambda = [](int) { return 2; };
// automatically converted to func_t and
// the local variable lambda reaches the end of its life
return lambda;
}
int main() {
const int a = retFun1()(0);
const int b = retFun2()(0);
std::cout << a << "," << b << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这两种情况都有明确定义吗?还是仅限于retFun1()?问题是:"函数指针指向的函数需要调用函子对象本身,还是在单独的函数中重新实现正文?" 任何一个都有意义,但事实上转换为函数指针特别需要一个无捕获的lambda,这表明它实际上可能是后者.
换句话说 - 我可以看到编译器可能想要实现这样的lambda的至少两种合理方式.一种可能的合法实现可能是编译器合成代码,如:
func_t retFun3() {
struct __voodoo_magic_lambda_implementation {
int operator()(int) const {
return 3;
}
static int plainfunction(int) {
return 3;
}
operator func_t() const {
return plainfunction;
}
} lambda;
return lambda;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下static,非static变体和非变体retFun都可以.但是,如果编译器实现lambda也是合法的:
static int __voodoo_impl_function(int x);
static struct __voodoo_maigc_impl2 {
int operator()(int) const {
return 4;
}
operator func_t() const {
return __voodoo_impl_function;
}
} *__magic_functor_ptr;
static int __voodoo_impl_function(int x) {
return (*__magic_functor_ptr)(x);
}
func_t retFun4() {
__voodoo_maigc_impl2 lambda;
// non-static, local lifetime
__magic_functor_ptr = λ //Or do the equivalent of this in the ctor
return lambda;
}
Run Code Online (Sandbox Code Playgroud)
然后retFun2()是未定义的行为.
GMa*_*ckG 20
§5.1.2/ 6说:
没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果.
强调我的.
换句话说:因为它是函数的地址,而函数没有生命周期,所以您可以随时调用该函数.你拥有的一切都是明确的.
这有点像你做的那样:
func_t retFun2()
{
int __lambda0(int)
{
return 2;
}
struct
{
int operator(int __arg0) const
{
return __lambda0(__arg0);
}
operator decltype(__lambda0)() const
{
return __lambda0;
}
} lambda;
return lambda; // just the address of a regular ol' function
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2558 次 |
| 最近记录: |