递归lambda和捕获(segfault)
recursive lambda and capture (segfault)
编译器
g++ (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010
代码段1(&
捕获)
#include <functional>
int main()
{
std::function<void ()> func = [&] () {
func();
};
return 0;
}
代码段2(func
捕获)
#include <functional>
int main()
{
std::function<void ()> func = [func] () {
func();
};
return 0;
}
两个代码段都可以编译,但为什么运行第二个代码段会导致分段错误?
捕获发生在构造std::function
之前。
因此,您捕获了std::function<void()> func
的未初始化(甚至不是默认构造的!)副本。std::function
的捕获本身就是UB(在构造变量之前复制变量!),调用它将是"更多的UB"(调用未构造的std::function
的副本!)。
引用案例捕获对func
的引用,即使在它被初始化之前,只要它只被初始化一次,它也是允许的。
引用情况的缺点是lambda仅在func
的范围内保持有效。一旦func
超出范围,其副本也将无效。根据我的经验,这很糟糕。
要实现真正的"全强度"递归lambda,您需要类似于y组合子的东西。
这里是一个C++14 y组合子的缩写:
template<class F>
auto y_combinate( F&& f ) {
return [f = std::forward<F>(f)](auto&&...args) {
return f(f, decltype(args)(args)...);
};
}
您向它传递一个lambda,该lambda期望将对自身的引用作为第一个参数:
std::function<void ()> func = y_combinate( [](auto&& self) {
self(self);
}
);
它完成其余的工作。
y组合子的要求是因为您不能在lambda的主体中访问自己的this
。所以我们加一个。
上面的y组合子只有90%,因为它不能完美地处理传入的函数对象的r/l值和常量。但它将在大部分时间内发挥作用。
这是一个稍微好一点的y组合:
template<class F>
struct y_combinate_t {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return f(*this, std::forward<Args>(args)...);
}
};
template<class F>
y_combinate_t<std::decay_t<F>> y_combinate( F&& f ) {
return {std::forward<F>(f)};
}
这使得使用效果更好:
std::function<void ()> func = y_combinate( [](auto&& self) {
self();
}
);
现在传入的CCD_ 12在被调用时不必自身传入CCD_。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 可组合的lambda/std::函数与std::可选
- C++中带有List类的迭代器Segfault
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 使用Vulkan hpp vk::enumerateInstanceVersion()会导致segfault
- 如何将lambda作为模板类的成员函数参数
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 在 lambda 捕获中声明的变量的类型推导
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 模板函数指针和lambda
- 两组使用lambda函数的大括号
- 使lambda不可复制/不可移动
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 将带有unique_ptr的可变 lambda 传递给 const&std::function
- 通过嵌套的lambda中的值捕获指针导致Segfault
- 递归lambda和捕获(segfault)
- c++11嵌套lambda编译segfault