小编典典

什么是“依赖于参数的查找”(又名 ADL,或“Koenig 查找”)?

all

关于什么是参数依赖查找有什么好的解释?许多人也将其称为 Koenig Lookup。

最好我想知道:

  • 为什么这是一件好事?
  • 为什么这是一件坏事?
  • 它是如何工作的?

阅读 81

收藏
2022-07-08

共1个答案

小编典典

Koenig LookupArgument Dependent
Lookup
描述了 C++
中的编译器如何查找非限定名称。

C++11 标准搂 3.4.2/1 规定:

当函数调用 (5.2.2) 中的后缀表达式是非限定 ID 时,可能会搜索在通常的非限定查找 (3.4.1)
期间未考虑的其他命名空间,并且在这些命名空间中,命名空间范围的友元函数声明 ( 11.3)
可能会发现其他不可见的。这些对搜索的修改取决于参数的类型(对于模板模板参数,模板参数的命名空间)。

用更简单的术语 Nicolai Josuttis 说1:

如果在函数的命名空间中定义了一个或多个参数类型,则您不必限定函数的命名空间。

一个简单的代码示例:

namespace MyNamespace
{
    class MyClass {};
    void doSomething(MyClass) {}
}

MyNamespace::MyClass obj; // global object


int main()
{
    doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}

在上面的示例中,既没有using-declaration 也没有 -directive,using但编译器仍然通过应用 Koenig
lookup
doSomething()将非限定名称正确识别为命名空间中声明的函数。MyNamespace __

它是如何工作的?

该算法告诉编译器不仅要查看本地范围,还要查看包含参数类型的命名空间。因此,在上面的代码中,编译器发现obj作为函数参数的对象doSomething()属于命名空间MyNamespace。因此,它会查看该名称空间来定位doSomething().

Koenig 查找的优势是什么?

正如上面的简单代码示例所示,Koenig 查找为程序员提供了便利和易用性。如果没有 Koenig
查找,程序员会产生开销,重复指定完全限定名称,或者改为使用大量using-declarations。

为什么要批评 Koenig 查找?

过度依赖 Koenig 查找会导致语义问题,有时会让程序员措手不及。

考虑 的示例 std::swap
,它是交换两个值的标准库算法。对于 Koenig 查找,在使用此算法时必须谨慎,因为:

std::swap(obj1,obj2);

可能不会显示与以下相同的行为:

using std::swap;
swap(obj1, obj2);

使用 ADL,swap调用哪个版本的函数将取决于传递给它的参数的名称空间。

如果存在命名空间A,并且如果A::obj1、、A::obj2A::swap()存在,则第二个示例将导致对
的调用A::swap(),这可能不是用户想要的。

此外,如果由于某种原因同时定义了A::swap(A::MyClass&, A::MyClass&)and std::swap(A::MyClass&, A::MyClass&),则第一个示例将调用std::swap(A::MyClass&, A::MyClass&),但第二个示例将不会编译,因为swap(obj1, obj2)它会模棱两可。

琐事:

为什么叫“淜oenig查找”?

因为它是由前 AT&T 和贝尔实验室研究员兼程序员 Andrew
Koenig
设计的。

进一步阅读:


1 Koenig 查找的定义在 Josuttis 的书中定义,C++ 标准库:教程和参考

2022-07-08