Lambda 表达式是通过创建一个带有重载函数调用运算符的类并将变量引用为成员来实现的。这表明 lambda 表达式的大小根据引用变量的数量而变化。但是,std::function 必须具有固定大小。理解 std::function 的实现至关重要。
可变大小函子的类型擦除
std::function 采用一种称为类型擦除的技术来处理以下函子尺寸可变。考虑一个 std::function 的简化示例,它将函数指针包装到 int(double):
struct callable_base { virtual int operator()(double d) = 0; virtual ~callable_base() {} }; template <typename F> struct callable : callable_base { F functor; callable(F functor) : functor(functor) {} virtual int operator()(double d) { return functor(d); } }; class function_int_double { std::unique_ptr<callable_base> c; public: template <typename F> function(F f) { c.reset(new callable<F>(f)); } int operator()(double d) { return c(d); } };
在此示例中,std::function 将 unique_ptr 存储到多态 callable_base 类型。对于不同的函子,动态创建并实例化从 callable_base 派生的新类型。 std::function 对象保持一致的大小,同时在堆中容纳各种大小的函子。
动态调度和优化
为了提高性能,实际实现std::function 优化动态调度并利用小对象优化。但是,基本概念保持不变。
std::function 副本的行为
std::function 的副本伴随着它们封装的可调用对象的副本。通过以下测试证实了这一点:
int main() { int value = 5; typedef std::function<void()> fun; fun f1 = [=]() mutable { std::cout << value++ << '\n' }; fun f2 = f1; f1(); fun f3 = f1; f2(); f3(); }
输出 демонстрирует (5, 5, 6),表示复制了函数对象,而不是共享状态。
对 std::function 实现的这种理解确保了它能够有效地使用不同大小的函子。
以上是`std::function` 如何处理可变大小的函子?的详细内容。更多信息请关注PHP中文网其他相关文章!