c++ - 什么是 "Argument-Dependent Lookup"(又名 ADL,或 "Koenig Lookup")?

标签 c++ argument-dependent-lookup name-lookup c++-faq

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

最好我想知道:

  • 为什么是好事?
  • 为什么是坏事?
  • 它是如何工作的?
  • 最佳答案

    Koenig 查找 , 或 Argument Dependent Lookup , 描述了编译器如何在 C++ 中查找非限定名称。
    C++11 标准 § 3.4.2/1 指出:

    When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function declarations (11.3) not otherwise visible may be found. These modifications to the search depend on the types of the arguments (and for template template arguments, the namespace of the template argument).


    简而言之,Nicolai Josuttis 指出:

    You don’t have to qualify the namespace for functions if one or more argument types are defined in the namespace of the function.


    一个简单的代码示例:
    namespace MyNamespace
    {
        class MyClass {};
        void doSomething(MyClass) {}
    }
    
    MyNamespace::MyClass obj; // global object
    
    
    int main()
    {
        doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
    }
    
    在上面的例子中,没有 using -声明也不是 using -directive 但编译器仍然正确识别出不合格的名称 doSomething()作为在命名空间 MyNamespace 中声明的函数通过应用 Koenig 查找。
    它是如何工作的?
    该算法告诉编译器不仅要查看局部作用域,还要查看包含参数类型的命名空间。因此,在上面的代码中,编译器发现对象obj ,这是函数 doSomething() 的参数, 属于命名空间 MyNamespace .因此,它查看该命名空间以定位 doSomething() 的声明。 .
    Koenig 查找的优势是什么?
    正如上面的简单代码示例所示,Koenig 查找为程序员提供了便利和易用性。如果没有 Koenig 查找,程序员会产生开销,需要重复指定完全限定名称,或者使用大量 using - 声明。
    为什么批评 Koenig 查找?
    过度依赖 Koenig 查找会导致语义问题,有时会让程序员措手不及。
    考虑 的例子 std::swap ,这是交换两个值的标准库算法。对于 Koenig 查找,在使用此算法时必须谨慎,因为:
    std::swap(obj1,obj2);
    
    可能不会表现出与以下相同的行为:
    using std::swap;
    swap(obj1, obj2);
    
    用ADL,哪个版本swap函数被调用将取决于传递给它的参数的命名空间。
    如果存在命名空间 A ,如果 A::obj1 , A::obj2 , 和 A::swap()存在,那么第二个示例将导致调用 A::swap() ,这可能不是用户想要的。
    此外,如果由于某种原因同时 A::swap(A::MyClass&, A::MyClass&)std::swap(A::MyClass&, A::MyClass&)被定义,那么第一个例子将调用 std::swap(A::MyClass&, A::MyClass&)但第二个不会编译,因为 swap(obj1, obj2)会模棱两可。
    琐事:
    为什么称为“Koenig 查找”?
    因为它是由前 AT&T 和贝尔实验室研究员和程序员设计的, Andrew Koenig .
    进一步阅读:
  • Herb Sutter's Name Lookup on GotW
  • 标准 C++03/11 [basic.lookup.argdep]:3.4.2 依赖参数的名称查找。

  • **1** Koenig 查找的定义在 Josuttis 的书中定义,*C++ 标准库:教程和引用*。

    关于c++ - 什么是 "Argument-Dependent Lookup"(又名 ADL,或 "Koenig Lookup")?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68558102/

    相关文章:

    c++ - 奇怪的 Unresolved external 错误

    c++ - GPS应用程序编译错误

    c++ - QSystemSemaphore::acquire() 中止

    c++ - 为什么 Boost.Range range_begin/end 自由函数对于 const 和非 const 引用都重载了?

    c++ -::(范围解析运算符) 前面没有任何内容

    c++ - 在 C++ 中将整数添加到数组中?

    c++ - ADL 不查找静态成员函数吗?

    c++ - 与条件 noexcept 和重载不一致

    c++ - 将 'typedef' 从基类传播到 'template' 的派生类

    c++ - 使用 C++20 using-enum-declaration 进行二义性名称查找