C ++ std :: set upper_bound迭代器行为

时间:2015-04-06 17:54:15

标签: c++11 stl iterator set

我对代码有查找问题,并且不确定迭代器测试的正确解释。问题是:我有一个集合并使用upper_bound进行查找,然后想要找到下一个最低元素。像这样:

#include <iostream>
#include <set>
#include <algorithm>

void exploreSet(std::set<int> &int_set, int key);

int main()
{
    std::set<int> int_set { 5, 10, 12, 17, 19 };
    exploreSet(int_set, 15);
    exploreSet(int_set, 4);
    return 0;
}


void exploreSet(std::set<int> &int_set, int key)
{
    auto it = int_set.upper_bound(key);
    if ( it==int_set.end() )
    {
        std::cout << "Nothing found.\n";
    }
    else
    {
        std::cout << "Found " << *it << ".\n";
        // Now find the next lowest value -- how?
        auto it_back = it;
        --it_back;
        if ( it_back==int_set.end() )
        {
            std::cout << "Nothing prior.\n";
        }
        else
        {
            std::cout << "Prior value:  " << *it_back << ".\n";
        }
    }
}

使用std = c ++ 14:

在gcc 4.9.2上运行此结果的结果输出
Found 17.
Prior value:  12.
Found 5.
Nothing prior.

这很有效。但为什么呢?

在通过upper_bound获得的迭代器上向后比较时,与std :: set :: end()进行比较是否正确?为什么或为什么不呢?

1 个答案:

答案 0 :(得分:2)

不,这是不正确的。递减等于begin()的迭代器是未定义的行为。见[bidirectional.iterators] / 1,表110:

  

<强>表达式
     --r
  断言/注意前/后条件
     pre:s存在r == ++s      帖子:r可以取消引用。

因此,正确的方法是将itint_set.begin()进行比较:

// Now find the next lowest value -- how?
if ( it == int_set.begin() )
{
    std::cout << "Nothing prior.\n";
}
else
{
    auto it_back = it;
    --it_back;
    std::cout << "Prior value:  " << *it_back << ".\n";
}

那就是说,我建议将std::set<int, std::greater<int>>lower_bound一起使用:

template <typename Set>
void exploreSet(const Set& int_set, int key) {
    auto it = int_set.lower_bound(key);
    if (it == int_set.end())
        std::cout << "Nothing found.\n";
    else
        std::cout << "Found " << *it << ".\n";
}

int main() {
    std::set<int, std::greater<int>> int_set { 5, 10, 12, 17, 19 };
    exploreSet(int_set, 15);
    exploreSet(int_set, 4);
}