C++ “什么是”呢;参数相关查找“;(又名ADL,或“Koenig查找”)?

C++ “什么是”呢;参数相关查找“;(又名ADL,或“Koenig查找”)?,c++,argument-dependent-lookup,name-lookup,c++-faq,C++,Argument Dependent Lookup,Name Lookup,C++ Faq,关于什么是参数相关查找,有哪些好的解释?许多人也称之为Koenig查找 最好我想知道: 为什么这是件好事 为什么这是一件坏事 它是如何工作的 在Koenig查找中,如果调用函数时未指定其名称空间,则还会在定义参数类型的名称空间中搜索函数名。这就是为什么它也被称为,简而言之 因为Koenig查找,我们可以这样写: std::cout << "Hello World!" << "\n"; std::cout在Koenig查找中,如果调用函数时未指定其名称空间,则也会在定义

关于什么是参数相关查找,有哪些好的解释?许多人也称之为Koenig查找

最好我想知道:

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

在Koenig查找中,如果调用函数时未指定其名称空间,则还会在定义参数类型的名称空间中搜索函数名。这就是为什么它也被称为,简而言之

因为Koenig查找,我们可以这样写:

std::cout << "Hello World!" << "\n";

std::cout在Koenig查找中,如果调用函数时未指定其名称空间,则也会在定义参数类型的名称空间中搜索函数名。这就是为什么它也被称为,简而言之

因为Koenig查找,我们可以这样写:

std::cout << "Hello World!" << "\n";

<代码> STD::CUT

<强>凯尼格查找>或>/Stult>,描述编译器在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.
}
在上面的示例中,既没有
使用
-声明,也没有
使用
-指令,但编译器仍然通过应用Koenig查找正确地将非限定名称
doSomething()
标识为命名空间
MyNamespace
中声明的函数

它是如何工作的? 该算法告诉编译器不仅要查看局部范围,还要查看包含参数类型的名称空间。因此,在上述代码中,编译器发现作为函数
doSomething()
的参数的对象
obj
,属于名称空间
MyNamespace
。因此,它查看该名称空间以定位
doSomething()
的声明

Koenig查找的优势是什么? 正如上面的简单代码示例所示,Koenig查找为程序员提供了方便和易用性。如果没有Koenig查找,程序员将需要重复指定完全限定名,或者使用大量的
声明

为什么要批评Koenig查找? 过度依赖Koenig查找会导致语义问题,有时会让程序员措手不及

为例,这是交换两个值的标准库算法。使用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查找”? 因为它是由美国电话电报公司和贝尔实验室的前研究员和程序员设计的

进一步阅读:
  • 标准C++03/11[basic.lookup.argdep]:3.4.2依赖于参数的名称查找


** 1 **凯尼格查找的定义如Josuttis的书中所定义的,即C++标准库:教程和参考文献*。

<强>凯尼格查找>或>/Stult>,描述了编译器在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.
}
在上面的示例中,既没有
使用
-声明,也没有
使用
-指令,但编译器仍然通过应用Koenig查找正确地将非限定名称
doSomething()
标识为命名空间
MyNamespace
中声明的函数

它是如何工作的? 该算法告诉编译器不仅要查看局部范围,还要查看包含参数类型的名称空间。因此,在上述代码中,编译器发现作为函数
doSomething()
的参数的对象
obj
,属于名称空间
MyNamespace
。因此,它查看该名称空间以定位
doSomething()
的声明

标签是什么
std::vector<boost::shared_ptr<int>> v;
auto x = begin(v);