Standard Library[lib]

C++ std::find: search a vector, array or string

Section
Standard Library [lib]
Standard
C++17
Compilers
MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2, Clang 23.1 (libc++)
Published
Length
7 min read
In this answer7 clauses
  1. 1What does std::find return when the value is not found?
  2. 2How do you check if a vector contains a value?
  3. 3How do you get the index of the element std::find found?
  4. 4How do you find by a condition with std::find_if?
  5. 5Can you use std::find on an array or a string?
  6. 6How do you find a key in a std::map or std::set?
  7. 7Which find should you use?

Abstract

std::find, from <algorithm>, searches a range for a value and returns an iterator to the first match, or the end iterator when nothing matches, so compare the result with end() before reading it. std::distance turns that iterator into an index, std::find_if searches by a condition, and a std::set or std::map has its own find() that searches its sorted keys in logarithmic time.

A row of six cells holding hatched shapes. Above, a framed triangle steps from cell to cell, grey where it has been, and stops in blue over the matching triangle in the third cell.
Figure 1 — One cell at a time, until a match.

std::find in C++ searches a range for a value: std::find(numbers.begin(), numbers.end(), 15) returns an iterator, a position in the container, to the first 15, or numbers.end() when there is none. Include <algorithm>, and always compare the result with end() before using it. It checks the elements one by one, so it works on any container.

Finding a lottery number in a vector, as a whole program:

[Example 1:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

int main() {
    std::vector<int> numbers{4, 8, 15, 16, 23, 42};

    auto it = std::find(numbers.begin(), numbers.end(), 15);
    if (it != numbers.end()) {
        auto index = std::distance(numbers.begin(), it);
        std::cout << "found " << *it << " at index " << index << '\n';
    }
}

— end example]

It printed:

[Example 2:
found 15 at index 2

— end example]

The answer is written for C++17 (Since When’s C++17 table). The samples were built with MSVC 19.44, Clang 19.1 (MSVC STL), GCC 16.2 and Clang 23.1 (libc++), as C++20 or C++23 where a line says so, and all four printed the same.

What does std::find return when the value is not found?

std::find returns the end iterator you passed in, which points one past the last element. That position is not an element, so compare the result with end() first and read *it only when they differ:

[Example 3:
auto it = std::find(numbers.begin(), numbers.end(), 99);
if (it == numbers.end())
    std::cout << "not found\n";    // it is end(): never read *it
else
    std::cout << "found " << *it << '\n';

— end example]

It printed not found. Both searches start at begin(): find 15 stops at the third cell and returns an iterator to it, while find 99 compares every value, matches none and returns end().

Six cells hold 4, 8, 15, 16, 23 and 42, followed by a dashed empty slot; begin() points at 4, end() at the slot. Find 15 steps from 4 to 15 and stops there; find 99 runs from begin() to end().
Figure 2 — std::find returns an iterator to the match, or end(), which is one past the last element.

How do you check if a vector contains a value?

Test whether std::find returned end(): std::find(v.begin(), v.end(), x) != v.end() is true when x is in the std::vector v. Wrapped in a small function, the call reads like the question:

[Example 4:
bool contains(const std::vector<int>& v, int x) {
    return std::find(v.begin(), v.end(), x) != v.end();
}

int main() {
    std::vector<int> numbers{4, 8, 15, 16, 23, 42};
    std::cout << std::boolalpha;
    std::cout << contains(numbers, 23) << '\n';    // true
    std::cout << contains(numbers, 7) << '\n';     // false
}

— end example]

It printed true, then false: 23 is one of the numbers and 7 is not. Since C++23, std::ranges::contains does the same in one call, without the function.

How do you get the index of the element std::find found?

Pass the container’s begin() and the iterator std::find returned to std::distance, from <iterator>, which counts the steps from the first to the second. In the first program, std::distance(numbers.begin(), it) is 2, the index of 15. It works on every container; call it only once the != end() test has passed, as that program does: on a miss it counts every element and returns the container’s size, which is no element’s index.

How do you find by a condition with std::find_if?

Call std::find_if with a predicate, a function that returns true or false, in place of the value: it returns an iterator to the first element for which the predicate returns true, or end(). The predicate is usually a lambda, a function written in place. Here it finds the first number above 15 and the player named Bo:

[Example 5:
struct Player {
    std::string name;
    int score;
};
// ...
std::vector<int> numbers{4, 8, 15, 16, 23, 42};
auto big = std::find_if(numbers.begin(), numbers.end(),
                        [](int n) { return n > 15; });
if (big != numbers.end())
    std::cout << *big << '\n';                 // 16

std::vector<Player> players{{"Ada", 75}, {"Bo", 92}, {"Lin", 60}};
auto bo = std::find_if(
    players.begin(), players.end(),
    [](const Player& p) { return p.name == "Bo"; });
if (bo != players.end())
    std::cout << bo->name << ' ' << bo->score << '\n';   // Bo 92

— end example]

All four printed 16, then Bo 92. The predicate must not change the element it is given.

Plain std::find compares each element with the value using ==, so on a vector of Player, a struct with no operator==, it does not compile:

[Example 6:
Player bo{"Bo", 92};
auto it = std::find(players.begin(), players.end(), bo);
// error: Player has no operator==, so find cannot compare

— end example]

MSVC’s first line of the error:

[Example 7:
error C2676: binary '==': 'Player' does not define this operator or a conversion to a type acceptable to the predefined operator

— end example]

The other three compilers reject it too, at greater length. To fix it, overload operator== for Player, comparing the name and the score, or search with std::find_if as above.

Can you use std::find on an array or a string?

Yes. For a built-in array, pass std::begin and std::end of the array as the range; on a std::string, std::find looks for one character. To find a word or any longer piece of text, call the string’s own find() member, which returns a position, or std::string::npos when the text is not there:

[Example 8:
int numbers[] = {4, 8, 15, 16, 23, 42};
auto it = std::find(std::begin(numbers), std::end(numbers), 23);
if (it != std::end(numbers))
    std::cout << "found " << *it << '\n';          // found 23

std::string word = "lottery";
auto t = std::find(word.begin(), word.end(), 't');
if (t != word.end())
    std::cout << "first t at " << (t - word.begin()) << '\n';  // 2

std::string text = "pick six numbers";
std::size_t at = text.find("six");
if (at != std::string::npos)
    std::cout << "six at " << at << '\n';          // six at 5
if (text.find("seven") == std::string::npos)
    std::cout << "no seven\n";                     // npos: a miss

— end example]

All four printed found 23, first t at 2, six at 5 and no seven. On the string, subtracting word.begin() from the iterator gave the position. The find() member belongs to std::string, not to <algorithm>, and it works with positions instead of iterators.

How do you find a key in a std::map or std::set?

Call the container’s own find() with the key: it returns an iterator to the element, or end() when the key is missing. A std::set and a std::map keep their keys sorted, so their find() takes logarithmic time: far fewer steps than std::find, which checks the elements one by one:

[Example 9:
std::set<int> drawn{4, 8, 15, 16, 23, 42};
auto it = drawn.find(16);                 // the set's own search
if (it != drawn.end())
    std::cout << "drawn " << *it << '\n';             // drawn 16

std::map<std::string, int> scores{{"Ada", 75}, {"Bo", 92}};
auto bo = scores.find("Bo");
if (bo != scores.end())
    std::cout << bo->first << ' ' << bo->second << '\n';  // Bo 92
if (scores.find("Zed") == scores.end())
    std::cout << "no Zed\n";                          // no Zed

// std::find on a map walks the pairs: it needs key and value
std::pair<const std::string, int> wanted{"Bo", 92};
auto walked = std::find(scores.begin(), scores.end(), wanted);
if (walked != scores.end())
    std::cout << "walked to " << walked->first << '\n';  // Bo

— end example]

All four printed drawn 16, Bo 92, no Zed and walked to Bo. A map’s element is a pair of key and value (first and second), so std::find on a map needs the whole pair and walks the elements in turn; the map’s find("Bo") takes the key alone. The other containers are in Standard library.

Which find should you use?

Use std::find for a value, std::find_if for a condition, and the container’s own find() for a set, a map or text in a string. Since C++20, std::ranges::find takes the container itself instead of two iterators, and C++23 adds std::ranges::contains for a plain yes or no:

[Example 10:
std::cout << std::boolalpha;

auto it = std::ranges::find(numbers, 15);  // C++20: ranges::find
if (it != numbers.end())
    std::cout << "found " << *it << '\n';             // found 15

bool has = std::ranges::contains(numbers, 15);  // C++23: contains
std::cout << has << '\n';                              // true

— end example]

As C++23, all four printed found 15 and true. As C++20, all four rejected the contains line, and as C++17 all four rejected std::ranges::find. On MSVC 19.44, C++23 is the /std:c++23preview switch.

You have Write
A value in a vector or an array std::find(first, last, x)
A condition std::find_if(first, last, pred)
A key in a set or a map c.find(key)
Text in a string text.find("six")
A yes or no question std::find(first, last, x) != last
A yes or no, in C++23 std::ranges::contains(v, x)
A whole container, in C++20 std::ranges::find(v, x)

Questions

Is std::find O(n)?

Yes. For a range of N elements, std::find makes at most N comparisons with operator==, because it may have to look at every element before it finds a match or reaches the end. A std::set or std::map finds a key with its own find() in logarithmic time instead.

What is the difference between std::find and std::find_if?

std::find looks for an element equal to a value, compared with ==. std::find_if takes a predicate, usually a lambda, and returns an iterator to the first element for which it returns true, such as the first number above 15. Both return the end iterator when nothing matches.

Does std::find work on a std::map?

Only with a whole element: each element of a map is a pair of key and value, so std::find needs both, walks the elements one by one, and with the key alone does not compile. To look up a key, call the map’s own find(), which takes the key alone, runs in logarithmic time and returns the map’s end() when the key is missing.

What is the difference between std::find and std::binary_search?

std::find works on any range, sorted or not, and returns an iterator to the match. std::binary_search requires the range to be sorted, or at least partitioned around the value, or the behavior is undefined; it makes at most about log2(N) comparisons and returns only true or false. For a position in a sorted range, std::lower_bound returns an iterator to the first element not less than the value, or last; the value is there only if that iterator is not last and the element equals it.

Which header is std::find in?

std::find is in <algorithm>, along with std::find_if and, since C++20, std::ranges::find. std::distance, which turns the iterator it returns into an index, is in <iterator>.

Read next

  1. C++ sort (std::sort): sort a vector or arrayStandard Library · Miriam Castellanos · written for C++17
  2. C++ map: std::map find, insert, erase and iterateStandard Library · Miriam Castellanos · written for C++17
  3. C++ string length: size(), length() and strlenStandard Library · Miriam Castellanos · written for C++17