使用不带前缀“std”的std :: sort(),也没有“using namespace std;”编译成功

时间:2017-01-05 18:19:58

标签: c++ stdvector

由于sort()中定义的namespace std必须始终用作std::sort。但即使没有std,以下代码也会正确编译。

#include <vector>
#include <algorithm>

int main()
{
    std::vector<int> nums = {4,3,1,7,2,0};
    sort(nums.begin(),nums.end());
}

ideone.com

但是这段代码没有。

#include <array>
#include <algorithm>

int main()
{

    std::array<int,5> nums = {4,1,8,9,6};
    sort(nums.begin(),nums.end());
}

在启用gcc 4.8.4标志的情况下使用-std=c++11

从这两段代码片段可以清楚地看出std::vector与此有关。但我无法弄明白。

2 个答案:

答案 0 :(得分:12)

这是argument-dependent lookup。如果使用typeid来检查所涉及的迭代器的类型:

#include <iostream>
#include <typeinfo>
#include <vector>
#include <array>

int main() {
    std::cout << typeid(std::vector<int>::iterator).name() << '\n';
    std::cout << typeid(std::array<int, 5>::iterator).name() << std::endl;
    return 0;
}

至少在Ideone上,您会得到以下输出:

N9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEE
Pi

借助Revolver_Ocelot对评论的帮助,我们发现这些类型为__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >int*

对于向量,在通常的名称查找失败后,编译器会在__gnu_cxxstd命名空间中搜索sort函数__gnu_cxx,因为它是__gnu_cxx::normal_iterator的命名空间{1}}和std因为它是其中一个模板参数std::vector<int, std::allocator<int> >的命名空间。它找到std::sort

对于std::array,迭代器只是int*,因此依赖于参数的查找不会搜索其他名称空间,也不会找到sort函数。

答案 1 :(得分:2)

这是参数依赖查找。根据Stroustroup的 C ++编程语言:第4版,这里有两个适用的规则:

  

1)如果参数是命名空间的成员,则为关联的命名空间   是封闭的命名空间。

     

2)如果参数是内置类型,则没有关联的命名空间。

在第一种和第二种情况下,begin()和end()返回迭代器。但是,C ++标准将迭代器定义为任何类型的任何变量,可以在其上执行迭代操作。 (换句话说,迭代器是一种通过模板强制执行的设计概念。)

根据另一个答案,第一种情况下的迭代器是与sort()属于同一名称空间的数据类型的变量。但是,第二种情况下的迭代器具有原始数据类型。根据规则#2,这些迭代器没有关联的命名空间。