【发布时间】:2016-02-11 16:59:19
【问题描述】:
std::function 已知存在性能问题,因为它可能会进行堆分配。承认,如果您是 100% 诚实的,那么在大多数情况下,一个堆分配应该不是问题……但是让我们假设在特定情况下进行堆分配是不可取的或禁止的。也许我们正在执行几百万次回调,并且不希望为此分配几百万次堆。
所以...我们希望避免这种堆分配。
Dr. Dobbs 的文章Efficient Use of Lambda Expressions and std::function 提出了关于利用标准推荐并在每个主流标准库中实现的小对象优化来优化std::function 的使用的建议。
这篇文章详细解释了标准库必须如何复制仿函数,因为 std::function 对象可能比原始仿函数的寿命更长(尽管你可以使用 std::ref,如果你确定它不会),这会很糟糕魔咒。此外,需要复制捕获,问题是:事先不知道闭包的确切类型(或其大小),因为它可能是具有任意数量捕获的任何类型的闭包,因此必须做出一些妥协。达到一定大小,捕获将保存在 function 对象内的存储中,除此之外,它将被动态分配。存储很小,从 12 到 16 字节不等,因此假设是 64 位构建,最多有两个指针(不包括实际的函数指针)。
博士。因此,Dobbs 建议(以及其他几个网站采纳该建议,似乎没有太多反对意见)捕获对包含对您实际想要捕获的内容的引用的结构的引用。这样,您只需捕获一个引用,这非常完美,因为它始终适合小型对象存储。
它是如何工作的?首先需要进行复制的假设是function 对象可能会超过原始闭包的范围。当然,这意味着它也比它所引用的结构以及从该结构内部引用的任何东西都要长。
这应该如何工作?而且由于我看不出它是如何工作的,有没有更好的知名配方来解决这个问题? (不引用无效对象)
【问题讨论】:
标签: c++ memory-management lambda c++14 std-function