Elgin Cahangirov
Elgin Cahangirov

Reputation: 2022

C++ returning invalid iterator

My task is:

Write a function that takes a pair of iterators to a vector and an int value. Look for that value in the range and return iterator to requested element.

My implementation for the above task is:

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

using data = vector<int>;
using iter = data::const_iterator;

iter contains(const data, iter, iter, int);

int main() {
    data numbers{1, 2, 5, 7, 9, 14, 18};
    iter b_iter = numbers.begin() + 2;
    iter e_iter = numbers.end();
    iter found = contains(numbers, b_iter, e_iter, 13);

    if (found == numbers.end())
        cout << "not found" << endl;
    else
        cout << *found << endl;

    return 0;
}

iter contains(const data container, iter b_iter, iter e_iter, int num) {
    while (b_iter != e_iter) {
        if (*b_iter == num)
            return b_iter;
        b_iter++;
    }

    return container.end();
}

As you see, I am iterating from beginning to the end and return if searched value is found. Otherwise, function return iterator to one pass the last element (container.end()). But this program outputs 0 to the console, where I expect not found. When updating my function's fist argument to reference to data rather than value like so:

iter contains(const data&, iter, iter, int);

Function works as expected and not found is printed to the terminal. Why passing data by value doesn't work as expected?

Upvotes: 1

Views: 507

Answers (1)

songyuanyao
songyuanyao

Reputation: 173014

When container is passed by value, it's a new vector copied from the argument. Then for return container.end();, the returned iterator belongs to container but has nothing to do with the original vector numbers.

You should just return the e_iter directly, and no need to pass the vector, just like STL algorithms do.

iter contains(iter b_iter, iter e_iter, int num) {
    while (b_iter != e_iter) {
        if (*b_iter == num)
            return b_iter;
        b_iter++; // or ++b_iter; for efficiency
    }

    return e_iter;
}

And check the result by comparing to e_iter too.

iter found = contains(b_iter, e_iter, 13);

if (found == e_iter)
    cout << "not found" << endl;
else
    cout << *found << endl;

Upvotes: 3

Related Questions