如果在容器中找不到 set::find() 的值

value of set::find() if not found in container

我正在努力理解 std::find()。下面是我的代码。

std::set::find searches the container for an element equivalent to val and returns an iterator to it if found, otherwise it returns an iterator to set::end.

但是当我给 find(100) 我得到 7 而不是 20。

#include <iostream>
#include <set>

using namespace std;

int main()
{
    set <int> s1{20, 7, 2};
    s1.insert(10);
    s1.insert(5);
    s1.insert(15);
    s1.insert(1);
    
    cout << "size()     : " << s1.size() << endl;
    cout << "max_size() : " << s1.max_size() << endl;
    cout << "empty()    : " << s1.empty() << endl;
    
    for(auto itr = s1.begin(); itr != s1.end(); itr++)
        cout << *itr << " ";
    cout << endl;
    
    cout << endl << "---- find(value) ----" << endl;
    auto a1 = s1.find(10);
    //cout << "find(10)  : " << a1 << " " << *a1 << endl;
    cout << "find(10)  : " << *a1 << endl;
    auto a2 = s1.find(100);
    cout << "find(100) : " << *a2 << endl;
    
    cout << endl << "---- count(value) ----" << endl;
    cout << "s1.count(10) : " << s1.count(10) << endl;
    cout << "s1.count(100) : " << s1.count(100) << endl;
    
    return 0;
}

输出:

size()     : 7

max_size() : 107374182

empty()    : 0

1 2 5 7 10 15 20

---- find(value) ----

find(10)  : 10

find(100) : 7


---- count(value) ----

s1.count(10) : 1

s1.count(100) : 0
auto a2 = s1.find(100);
cout << "find(100) : " << *a2 << endl;

在这里取消引用 (*a2) 结束迭代器。这是未定义的行为 - 请记住 s1.end() 指向 最后一个元素 之后的一个,不能取消引用。

你很不幸你从那个取消引用中得到了一个值 - 如果你的程序崩溃或以其他方式报告问题会更方便。但 UB 不一定非要以任何方式诊断。

如果您 运行 您的程序使用 Valgrind 的内存检查器(或您喜欢的等效程序),您可能已经发现了问题。但是很有可能无法检测到它(如果集合有 over-allocated,这很可能)。

问题 是您取消引用指向 s1.end() 的迭代器 a2 导致 未定义的行为.出现此问题是因为您在取消引用迭代器之前没有检查元素是否找到。

解决这个问题,您应该在取消引用迭代器之前添加显式检查。

//dereference only if the element was found
if(a2!=s1.end())
{
   std::cout << "find(100) : " << *a2 << std::endl; 
}
//otherwise print a message saying element not found 
else 
{
    std::cout<<"element not found"<<std::endl;
}

集合中不存在值 100。所以这个调用

auto a2 = s1.find(100);

returns 迭代器 s1.end()。您不能取消引用迭代器。此声明

cout << "find(100) : " << *a2 << endl;

调用未定义的行为。