C++中的std::identity是什么?(在函数对象中有什么作用)

1次阅读

std::identity 是 c++20 引入的标准库空操作函数对象,定义于 ,作用是原样返回参数;其类型为无状态、const 且 noexcept 的类,支持完美转发,适用于投影、泛型占位等场景。

C++中的std::identity是什么?(在函数对象中有什么作用)

std::identity 是个啥函数对象

它是个标准库提供的空操作函数对象,作用就是原样返回传入的参数,不改变、不计算、不判断。C++20 引入,定义在 <functional></functional> 头文件里。

常见错误现象:写 std::identity() 却编译失败——忘了 C++ 标准版本必须 ≥20,GCC/Clang 需加 -std=c++20;MSVC 19.30+ 才支持。

  • 它不是模板别名或类型推导辅助,而是一个具体的类类型:std::identity(注意没括号)
  • 实例化后是可调用对象,比如 std::identity{}(x) 等价于直接写 x
  • 和手写 [](auto&& x) { return x; } 行为一致,但更轻量、无捕获、有标准语义保证

什么时候非得用 std::identity

主要出现在泛型算法需要“透传”参数、又不能写死类型或值的场景,尤其是配合 std::ranges::transformstd::ranges::sortstd::ranges::max_element 这类接受投影(projection)参数的函数。

使用场景举例:对结构体数组按某个字段排序,但字段名本身是运行时无关的——这时用 std::identity{} 作为投影,表示“就用元素本身比较”,避免手写 Lambda 引入额外开销或生命周期问题。

立即学习C++免费学习笔记(深入)”;

  • std::ranges::sort(vec, {}, std::identity{}):等价于默认升序,但显式声明“不投影”,语义更清晰
  • 配合 std::views::transform 做类型擦除过渡:vec | std::views::transform(std::identity{}) 不改变值,但可能触发 view 的惰性求值优化
  • 模板元编程中作占位符:比如某算法模板参数要求一个可调用对象,你暂时不想做任何转换,std::identity 比自定义 Struct 更标准、更易读

std::identity 和手写 lambda 有啥区别

核心差异在类型唯一性、内联行为和 SFINAE 友好度上。编译器对 std::identity 有特殊认知,某些上下文能更好优化或推导。

性能影响:绝大多数情况下无差别;但某些老编译器对 lambda 捕获空结构体仍可能生成虚表或额外符号,而 std::identity 是无状态、无成员变量的 trivial 类型,sizeof 为 1 且 guaranteed copy elision。

  • lambda 类型每次出现都不同,无法跨函数签名复用;std::identity 类型固定,适合做模板参数约束(如 requires std::regular_invocable<:identity int></:identity>
  • 兼容性风险:C++17 项目不能用;若误写成 std::identity()(带括号),会触发函数声明解析(most vexing parse),变成函数声明而非对象构造
  • 调试时更友好:std::identity{} 在 gdb/lldb 中显示明确,而匿名 lambda 名字是编译器生成的乱码

容易被忽略的细节

std::identityoperator() 是 const-qualified 且 noexcept,返回类型严格匹配参数类型(保留引用、cv 限定符),这点比很多手写通用 lambda 更严谨。

比如传入 const std::String&std::identity{}(s) 返回的仍是 const std::string&;而 [](auto&& x) { return x; } 在某些编译器下可能退化为值返回,引发意外拷贝。

  • 它不接受多个参数:只有单参数重载,没有 operator()(T, U),别试图拿来当二元函数用
  • 不能用于需要 mutable 语义的场景——它天生 immutable,连 mutable 关键字都加不上
  • 头文件漏掉 <functional></functional> 时,部分编译器报错信息极不友好,可能只提示“no type named ‘identity’ in Namespace ‘std’”,而不是直接说“未包含头文件”

事情说清了就结束

text=ZqhQzanResources