std::mem_fn 自 c++20 起被弃用,因其类型擦除不彻底、sfinae 不友好、cv/引用限定符支持混乱,易导致推导失败或运行时 ub;推荐用 lambda 替代,语义清晰且编译期检查更强。

std::mem_fn 已被标记为 deprecated(自 C++20 起),不建议新代码使用;它功能上可被 lambda 或 std::bind 更安全、更清晰地替代。
为什么 std::mem_fn 在 C++20 后被弃用
它本质是把成员函数指针转成可调用对象,但类型擦除不彻底、SFINAE 友好性差、对 cv 限定符和引用限定符支持混乱。比如 std::mem_fn(&T::func) 对 const 成员函数的推导可能失败,或在绑定到右值对象时行为不可靠。
常见错误现象:error: no matching function for call to 'mem_fn' 或调用时崩溃(尤其在绑定到临时对象后调用)。
- 它不检查对象是否有效 —— 若传入空指针或已析构对象,运行时直接 UB
- 无法捕获
this的生命周期,比 lambda 更难控制所有权 - 与
std::function配合时额外开销更大(双重类型擦除)
用 lambda 替代 std::mem_fn 的典型写法
几乎所有 std::mem_fn 场景,都可用带捕获或参数转发的 lambda 实现,且语义明确、编译期检查强。
立即学习“C++免费学习笔记(深入)”;
例如原写法:
auto f = std::mem_fn(&std::string::size);
应改为:
auto f = [](const std::string& s) { return s.size(); };- 若需适配对象指针:
[&](std::string* p) { return p ? p->size() : 0; } - 若要完美转发(如配合
std::invoke):[](auto&& obj) -> decltype(auto) { return std::forward<decltype>(obj).size(); }</decltype> - lambda 自动参与重载解析,
std::mem_fn则常因模板推导失败静默退化
std::bind 也能替代,但要注意参数顺序
如果你习惯 std::bind 风格,它比 std::mem_fn 更健壮,但仍不如 lambda 直观。
例如绑定成员函数到第一个参数:
auto f = std::bind(&std::string::size, std::placeholders::_1);
- 注意:必须显式用
std::placeholders::_1占位,不能省略 -
std::bind返回对象有额外小对象开销,且 C++20 后也建议优先用 lambda - 若绑定到成员变量(如
&T::x),std::bind行为与std::mem_fn不同 —— 前者返回副本,后者返回引用(易引发悬垂引用)
真正容易被忽略的是:即使你没主动写 std::mem_fn,某些老库封装或 IDE 自动生成的补全仍可能推荐它。只要编译器开了 -std=c++20 或更高,就会触发 [[deprecated]] 警告 —— 别忽略这个警告,它背后是实实在在的可靠性缺口。










