首页 >后端开发 >C++ >尽管包装了不同大小的可调用对象,但'std::function”如何实现固定大小?

尽管包装了不同大小的可调用对象,但'std::function”如何实现固定大小?

DDD
DDD原创
2024-12-02 06:01:10728浏览

How Does `std::function` Achieve Fixed Size Despite Wrapping Callables of Varying Sizes?

如何实现 std::function:类型擦除和堆分配

std::function 的一个关键实现细节是它的能力包装任何可调用对象,包括 lambda 表达式。虽然 lambda 的大小不同,但 std::function 保持固定大小。这是通过一种称为类型擦除的技术来实现的。

举一个 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); }
};

这里,std::function 成立一个 unique_ptr 到一个基本的 callable_base 类型。对于所使用的每个唯一函子,派生类型可调用在堆上动态创建和实例化。这确保了 std::function 对象保持恒定的大小,同时允许它包装任何可调用对象。

std::function 的副本会触发内部可调用对象的副本,而不是共享状态。从可变捕获变量的值递增的测试中可以明显看出这一点:

int value = 5;
std::function<void()> f1 = [=]() mutable { std::cout << value++ << '\n'; };
std::function<void()> f2 = f1;
// Prints 5
f1();
// Prints 5 (copy of mutable state)
f2();

因此,std::function 使用类型擦除和堆分配有效地包装不同大小的可调用对象。堆分配用于根据包装的可调用实例化动态类型,确保 std::function 本身的固定大小。

以上是尽管包装了不同大小的可调用对象,但'std::function”如何实现固定大小?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn