探索 std::function 的实现
在 lambda 表达式的世界中,大小的概念变得流动,因为它们是本质上包装在具有可变大小引用的类中。然而,std::function 需要固定的大小。这就引出了一个问题:这是如何协调的?
答案在于类型擦除。让我们设想一个简化的实现:
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 存储指向基类的唯一指针。对于每个不同的函子,都会创建一个派生类型并动态实例化。因此,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(); // prints 5 fun f3 = f1; f2(); // prints 5 f3(); // prints 6 (copy after first increment) }
输出表示隔离副本而不是共享状态,因为不同的调用独立地增加值。
以上是尽管处理可变大小的 Lambda 表达式,std::function 如何保持固定大小?的详细内容。更多信息请关注PHP中文网其他相关文章!