Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe in C++ to subtract from container.end()?

That is, providing that container is not empty, can I safely do this:

std::vector<int> container;
container.push_back( 0xFACE8D );
auto last = container.end() - 1;

and this:

EDIT: replaced -1 with -- here:

std::list<int> container;
container.insert( 0xFACE8D );
auto last = container.end();
--last;

and again for arbitrary non-empty container?

EDIT: let me clarify the question.

Sometimes perfectly legal code behaves incorrectly. The question is: assuming that the above code compiles, is it safe to do something like that?

It should be safe for ordinary C-style arrays because the corresponding iterators are just pointers. But is it safe for more complicated containers?

Suppose that one implements list with iterators like this one:

class MyListIterator {
    MyListIterator *prev, *next;
    MyListIterator * operator--() { return prev; }
    ...
};

class MyList {
    MyListIterator *end() { return NULL; }
    ...
}; 

Then an attempt to decrement container::end(), despite being perfectly legal syntactically, would cause a segfault.

I hope, though, that stl containers are much smarter than that. Thus the question on the guarantees on the above stl::list code behavior, if any.

like image 758
Michael Avatar asked Oct 01 '15 23:10

Michael


1 Answers

std::vector returns random-access iterators, so yes, this is safe with vector.

std::list returns bidirectional iterators. They can be incremented (++) and decremented (--), but don't allow for arbitrary arithmetic (+, -) or relative comparisons (>, <). It's not safe with list.

You can use std::advance on bidirectional iterators to advance or rewind arbitrary amounts. In C++11 you can use std::prev in place of iter - 1.

like image 153
John Kugelman Avatar answered Oct 17 '22 16:10

John Kugelman