25

std::function<void(int&)>来自 C++11 的它有什么魔力sizeof = 32?如果我将函数引用存储为指针,它只会花费8 bytes(在 64 位机器上)。

4

2 回答 2

16

因为std::function<Signature>这是一个有趣的对象大小和分配之间的权衡:对于小型函数对象,最好避免分配。另一方面,这样做会增加对象的大小。为了使小函数优化有用并且在实际调用对象时不引入开销,对象大小需要至少是两个指针加上一些内存来存储简单的函数对象。似乎 32 字节的大小正是这个(在sizeof(T*)8 的系统上)。

也就是说,std::function<Signature>对象内部存储了继承层次结构:基类提供要调用的接口,委托给实现调用接口的模板化派生(可能还有一些clone()功能)。在针对大小优化的实现中,函数对象只会保留一个指向基址的指针,但为了避免分配,它会留出一些内部存储空间来分配整个对象并指向该对象(内部指针在实际调用时避免了一个条件函数对象)。对象所需的内存是一个虚函数指针加上std::function<Signature>初始化对象的实际函数对象的任何数据。为了使成员函数与它们的对象相适应,似乎再多两个词就相当小了。

于 2012-11-21T23:15:54.410 回答
8

std::function确实很神奇,因为它可以从任何可调用对象构造!它会很乐意为你存储任何数量的状态,即使在表面上你只保留了一个微不足道的void(int&)签名。

这种魔法肯定是有代价的,它通常在内部使用某种类型的擦除(即动态分配和虚拟调度)。细节各不相同,但生成的对象肯定是“沉重的”——这就是为什么应该避免使用它们,auto而在可行的情况下使用模板!

于 2012-11-21T23:19:42.373 回答