Aaron McDaid
Aaron McDaid

Reputation: 27133

converting iterator to pointer - especially at end()

I'm wondering if this is defined:

vector<int> v;
v.push_back(1337);
int * p1 = &*vi.end();

(Update 1 If this is undefined, I'd like to know more about exactly where my error is. For example, perhaps the reference int &r = &*(v.data()+v.size()) is legal in general, but *end() isn't required to return that. )

(Update 2 I'm really just curious about the pedantic language-lawyer question as to what can be defined. I have no difficulty coding uncontroversial workarounds :-) )

Anyway, of course, using an end-iterator like this looks bad. But first, consider this:

int array[3];
int * p2 = array + 3;

Clearly p2 is defined.

The, according to this answer, p2 is equivalent to p3 in this code: (if you're using C99):

int array[3];
int * p2 = array + 3;
int * p3 = &array[3]; // looks bad, but OK in C99

(I'm more curious about C++ though, and a comment to that answer implies that C++ allows it also. So, the above C99-compatible code is defined in C++.)

Moving closer to C++, I think I can write this:

int & r1 = *p3;

I agree that r1 looks really bad. And certainly, it would be UB if we did something like int x= r1;. That is UB because it involves an lvalue-to-rvalue conversion. But can we say that r1 is still just an lvalue? And therefore we can take its address?

int * p3 = &r1;

If all this is valid, then we can argue that a one-past-the-end reference is generally valid - for C-arrays at least. So, what can we say about *v.end()?

The operator*() method returns an int& reference. Does the standard require that it return one of these one-past-the-end references that we are allowed to take the address of?

Bonus: what if the vector is empty? In particular, is (&*v.end())==(&*v.begin())

Upvotes: 2

Views: 95

Answers (2)

Meixner
Meixner

Reputation: 695

v.end() points one beyond the last element. Therefore, dereferencing it is illegal.

You could use *(v.end()-1) to get the last element as long as v.size()>=1.

(Or use &*(v.end()-1) to get a pointer to it.)

Upvotes: -1

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275350

No, any * on v.end() is illegal.

You can do v.data()+v.size() instead for a pointer to the end, and v.data() for a pointer to the beginning.

This is defined even for an empty std::vector.

Upvotes: 4

Related Questions