ADL 参数依赖查找
更新时间:2026-10-01。理解
swap(x,y)、begin(x)为何在泛型代码中自动选对版本。
一、机制
对 ns::Type t; f(t);,除当前作用域外,还会在 ns 中查找 f。于是:
cpp
template<class T> void s(T& a,T& b){ using std::swap; swap(a,b); }若 T 命名空间有更优 swap,ADL 选中它,否则退回 std::swap。
二、定制点与风险
运算符、范围 for 的 begin/end 都靠 ADL;C++20 ranges 用“不可见的定制点对象”防止 ADL 劫持;隐藏 friend 只通过 ADL 可见、收敛重载。坑是无意中把同名函数纳入候选导致二义/劫持。

常见坑
- 以为不加限定一定找不到。
- 泛型里直接
std::swap错过用户重载。 - 命名空间开放同名函数造成意外劫持。
小结
总结
ADL(参数依赖查找 / Koenig lookup)指调用一个无限定的函数时,编译器除了当前作用域还会到实参类型所在的命名空间里查找,这正是泛型惯用法 using std::swap; swap(a,b); 能自动选中用户为自己类型定制的 swap、否则退回 std::swap 的原因,运算符重载和范围 for 的 begin/end 也都依赖它;要配合 using 声明使用最稳,泛型里直接写死 std::swap 反而会错过用户重载,同时警惕命名空间里的同名函数被意外纳入候选造成二义或"劫持",C++20 ranges 用定制点对象(cpo/Niebloid)和隐藏 friend 来收敛这种风险。