来自C ++ 11的std::function<void(int&)>
与sizeof = 32
的神奇之处是什么?如果我将函数引用存储为指针,则只需8 bytes
(在64位计算机上)。
答案 0 :(得分:15)
对于std::function<Signature>
,它是对象大小和分配之间的权衡,这是有趣的:对于小函数对象,希望避免分配。另一方面,这样做会增加对象的大小。为了使小函数优化变得有用并且在实际调用对象时不引入开销,对象大小需要至少两个指针加上一些内存来存储简单的函数对象。似乎32字节的大小就是这样(在sizeof(T*)
为8的系统上)。
也就是说,std::function<Signature>
对象内部存储一个继承层次结构:基类提供要调用的接口,委托给实现调用接口的模板化派生(加上,可能还有一些clone()
功能)。在针对大小优化的实现中,函数对象只保留指向基类的指针,但是为了避免分配,它会留出一些内部存储来分配整个对象并指向该对象(内部指针在实际调用时避免了一个条件)功能对象)。对象所需的内存是虚函数指针加上std::function<Signature>
对象初始化的实际函数对象的任何数据。为了容纳成员函数及其对象,似乎还有两个单词相当小。
答案 1 :(得分:8)
std::function
确实很神奇,因为它可以从任何可调用对象构建!它会愉快地存储任何数量的状态,即使表面上你保留了一个微不足道的void(int&)
签名。
这种魔法肯定会附加价格,它通常在内部使用某种类型的擦除(即动态分配和虚拟调度)。细节有所不同,但由此产生的对象肯定是重的&#34; - 这就是为什么在可行的情况下应该避免使用auto
和模板的原因!