复制std :: function有多贵?

时间:2017-06-06 11:29:29

标签: c++ c++11 std-function

虽然std::function是可移动的,但在某些情况下它不可能或不方便。复制它会有重大的惩罚吗?

是否可能取决于捕获变量的大小(如果它是使用lambda表达式创建的)?它是依赖于实现的吗?

2 个答案:

答案 0 :(得分:9)

std::function通常实现为值语义,小缓冲区优化,虚拟调度,类型擦除类。

这意味着如果您的状态很小,副本将不涉及堆分配(除了状态的复制之外)和一些间接(以找到如何复制此特定状态)。

如果您的状态很大(例如,当前MSVC上大于两个std::string),则需要额外的堆分配来存储状态。

这不是你想要按每像素每帧进行的事情,但它并不是非常昂贵。

您的特定编译器和库版本如何实现std::function可能会有所不同,但我不知道任何与上述版本有很大不同。

因此,在以下代码中:

std::function<std::string()> f = [s = "hello"s]{ return s; };

复制f将涉及MSVC上的0堆分配。

然而,这段代码:

std::function<std::string()> g = [a = "a"s, b = "b"s, c = "c"s]{ return a+b+c; };

需要堆分配才能复制g

(是的,这两个都是非常愚蠢的功能对象。)

有一个有效的要求是,对std::function中的某些情况(函数指针,成员函数指针)应用小缓冲区优化(SBO),因为预期它们在分配内存时不会失败。一旦你编写了一个SBO案例,使其更通用并不难,所以大多数std::function实现存储小对象&#34;在他们自己内部&#34;堆上的更大的对象。

但是,标准没有规定此阈值,这对性能成本很重要,因此如果性能非常重要,那么您必须进行配置以确保您的实施能够实现。

答案 1 :(得分:6)

确实依赖于实现。它还取决于您在validate_password中存储的确切内容。它肯定不像简单地复制C风格的函数指针那么便宜。

最好的办法是让你尝试以清晰方便的方式编写代码,然后,如果运行速度不够快,请对其进行分析。如果您需要最终表现,您可能会发现std::function根本不适合。