C++
std::find
reverse iterators
programming
STL

Using stdfind With Reverse Iterators

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

std::find works with reverse iterators just as it does with normal iterators, as long as the iterator category requirements are met. The main thing that confuses people is not the search itself, but how to interpret the returned iterator and how to convert it back to a forward iterator correctly.

Searching from the End

If you want to find the last matching value in a container, reverse iterators are often the easiest approach.

cpp
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5int main() {
6    std::vector<int> values{1, 4, 2, 4, 7};
7
8    auto rit = std::find(values.rbegin(), values.rend(), 4);
9
10    if (rit != values.rend()) {
11        std::cout << "Found from reverse view: " << *rit << '\n';
12    }
13}

This finds the first 4 in reverse traversal, which corresponds to the last 4 in the normal forward view of the vector.

What the Returned Reverse Iterator Means

When std::find returns a reverse iterator:

  • dereferencing it gives the matched element
  • incrementing it moves backward through the underlying container
  • comparing it against rend() tells you whether a match was found

This part is straightforward. The subtle part comes when you want the equivalent normal iterator.

Converting with .base()

For a reverse iterator rit, rit.base() does not point to the same element. It points to the forward iterator one position after the element viewed by the reverse iterator.

cpp
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5int main() {
6    std::vector<int> values{1, 4, 2, 4, 7};
7
8    auto rit = std::find(values.rbegin(), values.rend(), 4);
9    if (rit != values.rend()) {
10        auto it = rit.base();
11        std::cout << "base() points to: " << *it << '\n'; // prints 7
12    }
13}

That surprises many people the first time they see it.

Getting the Forward Iterator to the Same Element

If you need a normal iterator to the matched element itself, move one step back from base().

cpp
1#include <algorithm>
2#include <iostream>
3#include <vector>
4
5int main() {
6    std::vector<int> values{1, 4, 2, 4, 7};
7
8    auto rit = std::find(values.rbegin(), values.rend(), 4);
9    if (rit != values.rend()) {
10        auto it = std::prev(rit.base());
11        std::cout << "Forward iterator value: " << *it << '\n';
12        std::cout << "Index: " << std::distance(values.begin(), it) << '\n';
13    }
14}

That std::prev adjustment is the crucial conversion step.

Why Reverse Iterators Are Useful

Using reverse iterators is often cleaner than:

  • writing a manual reverse loop
  • scanning from the front and remembering the last match
  • subtracting indexes manually

For containers such as std::vector, std::string, and std::deque, reverse iterators make "find the last matching item" read naturally.

Example with std::string

cpp
1#include <algorithm>
2#include <iostream>
3#include <string>
4
5int main() {
6    std::string text = "abc:def:ghi";
7
8    auto rit = std::find(text.rbegin(), text.rend(), ':');
9    if (rit != text.rend()) {
10        auto it = std::prev(rit.base());
11        std::cout << "Last colon at index "
12                  << std::distance(text.begin(), it)
13                  << '\n';
14    }
15}

This is a very readable pattern for last-occurrence searches.

Prefer Dedicated Algorithms When They Exist

For some containers or string types, there may be a more direct function such as rfind. If the type already gives you the operation you want, use that first. Reverse iterators are most useful when you want a generic STL algorithm or need logic that goes beyond a built-in convenience method.

Common Pitfalls

The biggest mistake is assuming rit.base() points to the found element. It actually points one position past it in forward-iterator terms.

Another issue is dereferencing rit.base() without checking what it means semantically. That often yields the next element instead of the matched one.

A third problem is forgetting to compare against rend() when searching in reverse. rend() is the "not found" sentinel for reverse traversal.

Summary

  • 'std::find works normally with reverse iterators.'
  • Searching with rbegin() and rend() is a clean way to find the last matching element.
  • A reverse iterator's .base() points one element past the reverse view's current element.
  • Use std::prev(rit.base()) when you need the forward iterator to the matched item.
  • Prefer container-specific helpers such as rfind when they already solve the problem directly.

Course illustration
Course illustration

All Rights Reserved.