给定的
class C;
void do_something_else( std::function< void ( C &)> );
class A1{
void do_something(C &);
void test(){
int i;
for (i=0; i<100; i++)
do_something_else([this]( C & C_){ this->do_something(C_); } );
}
};
class A2{
std::function< void ( C &)> lambda;
void do_something(C &);
A2():lambda([this]( C & C_){ this->do_something(C_) ;}){}
void test(){
int i;
for (i=0; i<100; i++)
do_something_else(lambda);
}
};
A1::test()
和A2::test()
答案 0 :(得分:2)
std::function
被要求使用小对象优化来在自己内部存储小的invokable,而无需在免费商店上分配内存。
你的lambda很小,所以在一个典型的基于类型擦除的实现中从它创建一个std::function
涉及设置虚拟函数表指针的粗略等价物,并在位于内部的内存缓冲区中执行放置构造std::function
本身。
lambda的大小是一个指针(this
)。虚函数表将编写另一个常量(或者可能是一些常量指针,具体取决于实现是否以std::function
内的vtable“内联”以大小为代价来换取位置。
任何非平凡的操作都会压低创建如此小的std::function
的成本。
此外,您使用std::function< void ( C &)>
按值:这意味着第一个展示位置构建std::function
,而第二个副本 - 从现有std::function
构建它。复制构造可能涉及使用虚拟表来复制状态,但优化的std::function
可以保留“平凡可复制状态”的标志以避免该间接(以分支为代价)。
接下来,编译器可能能够通过内联类实例并将分配展开到内存来解码您对std::function
所执行的操作。它甚至可能完全消除std::function
的存在。编译器在这方面继续变得更好。
最后,您注意到您在微基准测试中看到了4%的性能差异。这是(弱)证据表明没有显着差异,因为微基准环境和“真实”环境之间的差异将会超过这么小的差异。
使用以使代码更清晰的方式。