0

I have following code, that fails due to read access violation:

#include <vector>
using namespace std;

vector<int>::iterator myIterator;

void foo(vector<int> vec) {
    myIterator = vec.begin(); 
}

int main()
{
    foo({ 10, 20, 30, 40 });
    *myIterator; // Here it fails.
    return 0;
}

After some debugging, I found, that myIterator becomes invalid, when the function foo() is completed.

So what am I doing wrong?

FireFragment
  • 596
  • 1
  • 4
  • 15
  • The variable `vec` is gone before the line that you marked. Where do you think the iterator should point? – Brick Jun 18 '21 at 18:25
  • You're getting an iterator to a temporary vector. For that to work, you need to create a named variable in `main` to hold the vector, then pass a reference to it to `foo`. – 1201ProgramAlarm Jun 18 '21 at 18:26
  • 1
    This example is beautiful. It's short and sweet. But it doesn't really give us enough to know what your goal is, and this makes it hard to offer an optimal solution. – user4581301 Jun 18 '21 at 18:41
  • What do you think copying an iterator does? What do you think an iterator _is_? – Mooing Duck Jun 18 '21 at 18:45
  • C++ is not Java or JavaScript. C++ is a value-based language -- when you pass a vector by value as you're doing, a *copy* of the vector is made, thus that copy disappears once the function returns. There are no reference shenanigans going on like in those other languages, where passing an object means that a reference is passed. If you want a reference in C++, you have to explicitly tell C++ you want a reference. – PaulMcKenzie Jun 18 '21 at 18:59

1 Answers1

4

vec is only defined within the scope of foo. Since myIterator is an iterator that points to vec, it is no longer valid outside of foo. Trying to dereference such an iterator results in a read access violation.

You need to define vec somewhere (in main for example), then pass a reference to it in foo, something like:

void foo(vector<int>& vec) {
    myIterator = vec.begin();
}

int main() {
    vector<int> vec = {10, 20, 30, 40};
    foo(vec);
    *myIterator;
    return 0;
}
Wais Kamal
  • 5,858
  • 2
  • 17
  • 36
  • 1
    its not a null pointer its a dangling pointer – Alan Birtles Jun 18 '21 at 18:30
  • 3
    Consider calling it an "invalidated iterator", since it isn't necessarily a pointer and certainly isn't "null". Dereferencing one would be "Undefined Behavior". Promising a read access violation isn't correct. – Drew Dormann Jun 18 '21 at 18:31
  • @DrewDormann it is a pointer that was pointing to a vector element. – Wais Kamal Jun 18 '21 at 18:33
  • 1
    @WaisKamal take a look at what [`std::vector::begin()` returns](https://en.cppreference.com/w/cpp/container/vector/begin). There is no mention of a "pointer". See also https://stackoverflow.com/questions/2728190 – Drew Dormann Jun 18 '21 at 18:35
  • Technically there might not be any pointer involved. The iterator is usually implemented with a pointer, but it doesn't have to be. A good-sized chunk of Iterator's job is to hide what's really going on. – user4581301 Jun 18 '21 at 18:35