为什么' std::prev '不会用' std::unordered_set '的迭代器引发错误?

Why `std::prev` does not fire an error with an iterator of `std::unordered_set`?

本文关键字:std 迭代器 错误 set prev 为什么 unordered      更新时间:2023-10-16

我的问题与下面链接的问题有关。unordered_map?中的双向迭代器

由于我不知道std::unordered_set不支持双向迭代器,我碰巧写了一段类似于下面的代码。

int main(){
    unordered_set<int> y{4};
    std::cout << *(std::prev(y.end())) << std::endl;
}

程序已编译,但最后一行代码使程序崩溃。对此感到困惑的是,我遇到了一个相关的问题。然而,我仍然不明白为什么这个程序被编译而不是抛出错误消息,而链接代码中的代码(这是boost::unordered_set)无法编译。你能解释一下吗?

供参考,我使用Mingw64与g++ 4.8.2/Windows 7/64位环境。

std::prev只产生双向迭代器的定义行为。


GNU ISO c++库(GCC 4.8.2使用)使用std::advance来实现std::prev, std::advance本身是这样实现的:

  • 用于随机访问迭代器:

    __i += __n;
    
  • 用于双向迭代器:

    if (__n > 0)
      while (__n--)
        ++__i;
    else
      while (__n++)
        --__i;
    
  • 用于所有其他迭代器:

    while (__n--)
      ++__i;
    

因此,您可以看到,对于unordered_set的迭代器,该函数实际上没有使用operator--,从而在您链接的另一个问题中产生编译错误。


你有责任确保传递给std::prev的迭代器是双向的。如果不是这样,c++标准就不能保证会发生什么。GCC选择静默地忽略它,但它也可能使程序崩溃。

std::prev可能使用了std::advance,其中,当参数(Input Iterator)不是双向时,行为是未定义的。