关于std::mem_fn的性能开销及与直接调用成员函数的对比问询
std::mem_fn的性能开销分析
首先直接给结论:在开启优化的主流编译器(GCC、Clang、MSVC的O2/O3级别)下,std::mem_fn几乎没有额外性能开销,和直接调用成员函数的效率完全一致。你的预期其实是对的,但它和std::function的机制有本质区别,这也是它能做到零开销的关键。
为什么std::mem_fn能做到零开销?
和std::function的类型擦除多态不同,std::mem_fn是静态类型绑定的模板包装器:
- 它的实例化完全在编译期完成,编译器明确知道它包装的是哪个成员函数(包括成员函数的签名、所属类)。
- 它的内部实现非常轻量,通常就是持有一个成员函数指针,调用
operator()时只是做简单的参数转发,这个过程会被编译器完全内联。
举个实际的代码例子:
struct MyClass { int add(int a, int b) { return a + b; } }; // 直接调用成员函数 MyClass obj; int result1 = obj.add(2, 3); // 用std::mem_fn包装后调用 auto add_fn = std::mem_fn(&MyClass::add); int result2 = add_fn(obj, 2, 3);
在O2优化下,编译器会把这两段代码编译成完全相同的机器码——没有额外的函数调用、没有多余的指令,和直接调用毫无区别。
和std::function的性能差异
你提到担心它和std::function一样有开销,但其实两者的设计目标完全不同:
- std::function是通用的多态函数包装器,支持类型擦除,可以容纳任何可调用对象(函数指针、lambda、mem_fn实例等),这就导致它必须有运行时的分发逻辑(通常是虚函数调用),即使开启优化也会有少量开销(除非触发小对象优化且编译器能内联,但这不是必然的)。
- std::mem_fn是专门针对成员函数的轻量包装,不支持类型擦除,所有绑定信息都在编译期确定,因此没有运行时额外开销。
特殊情况说明
如果包装的是虚成员函数,调用时会有虚函数的开销,但这不是std::mem_fn带来的——直接调用虚成员函数本身就有这个开销,mem_fn只是转发了这个调用,不会增加额外成本。
内容的提问来源于stack exchange,提问作者Danra
相关产品推荐
相关产品推荐

