关于std::lower_bound中comp谓词Type1参数限制的疑问
std::lower_bound谓词参数类型的疑问 背景参考
std::lower_bound的谓词comp是一个二元谓词,要求第一个参数小于第二个参数时返回true,其推荐签名为:
bool pred(const Type1 &a, const Type2 &b);
文档中提到:虽然签名不需要严格带const &,但函数不能修改传入的对象,且必须能接受(可能为const的)Type1和Type2的所有值,无论值类别如何。因此:
Type1 &不被允许Type1也不被允许,除非Type1的移动操作等价于拷贝操作(C++11起)
用户疑问
我理解Type1 &不被允许是因为可能导致谓词修改传入对象,但为什么Type1(值传递)也不被允许?仅仅是优化问题,还是有更深层的原因?
核心原因:语义一致性与行为正确性
Type1值传递不被允许的核心原因不是优化,而是要保证谓词的行为符合算法的语义要求,具体来说有两点:
避免破坏容器元素状态
算法会向谓词传递各种值类别(左值、右值)的参数。如果用值传递Type1,当传入右值时会触发移动构造。如果Type1的移动操作会改变原对象状态(比如移动后原对象的成员被置空),就会破坏lower_bound依赖的容器元素状态——毕竟这只是个查询类算法,不该修改容器里的元素。
只有当移动操作等价于拷贝操作时(比如int这类基本类型,或者移动后原对象状态和拷贝完全一致的类型),才不会出现这个问题,所以这种情况例外。保证谓词的通用可调用性
算法要求谓词能接受const和非const的Type1值。如果用值传递Type1,对于那些禁用拷贝/移动的类型,谓词会直接无法调用。而const Type1&可以完美适配所有值类别,同时保证不会修改原对象。
补充:关于Type1 &的问题
你推测的“可能修改对象”是对的——非const引用会允许谓词函数修改传入的参数,而lower_bound这类算法要求谓词是纯函数(不修改输入,相同输入返回相同结果),所以非const引用的签名不符合算法的语义约束。
内容的提问来源于stack exchange,提问作者Vinod

