Unimatrix_001
asked on
Using vector.begin() outside of range.
Hello,
temp.insert(temp.begin(), pile.begin()+3-5, pile.end());
Will this crash, or will the "pile.begin()+3-5" be calculated to just pile.begin()? Likewise, if I tried to do pile.end()+5, will that calculate to pile.end()?
Thank you,
Uni
temp.insert(temp.begin(), pile.begin()+3-5, pile.end());
Will this crash, or will the "pile.begin()+3-5" be calculated to just pile.begin()? Likewise, if I tried to do pile.end()+5, will that calculate to pile.end()?
Thank you,
Uni
If you try to perform iterator arithmetic and the result exceeds the end you'll get undefined behavior if you then try to manipulate the element that the result refers to ... this is the same as if you performed pointer arithmetic and tried to access beyond the end of an array. Your result must fall within the begin() to end() range of the vector before you can use it safetly.
Visual Studio will try and check this for you if _SECURE_SCL is defined as 1
http://msdn.microsoft.com/en-us/library/aa985896(VS.80).aspx
http://msdn.microsoft.com/en-us/library/aa985896(VS.80).aspx
_SECURE_SCL
Defines whether Checked Iterators are enabled. If defined as 1, unsafe iterator use causes a runtime
error. If defined as 0, checked iterators are disabled. The exact behavior of the runtime error depends
on the value of _SECURE_SCL_THROWS. The default value for _SECURE_SCL is 1, meaning checked iterators
are enabled by default.
To enable checked iterators, set _SECURE_SCL to 1:
#define _SECURE_SCL 1
To disable checked iterators, set _SECURE_SCL to 0:
#define _SECURE_SCL 0
ASKER
Hm, is there anyway to bound the iterator to .begin and .end so that it is impossible to exceed them with any iterator arithmetic?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Rather than performing the arithmetic directly on the iterator why don't you perform it as number arithmetic and make sure the result is within v.size() before you try and add it to c.begin()? Quick example...
if(pile.size () >= 3.5)
{
temp.insert(temp.begin(), pile.begin()+3-5, pile.end());
}
else
{
//oops
}
if(pile.size () >= 3.5)
{
temp.insert(temp.begin(), pile.begin()+3-5, pile.end());
}
else
{
//oops
}
You can only increment an iterator if the iterator is dereferenceable.
You can only decrement an iterator if the resulting iterator would be dereferenceable.
past-the-end iterators are not guaranteed to be dereferenceable.
Since vector iterators are random access iterators, the operator+ and operator- are also defined for it, so you can add (or subtract) an integer value to (from) it. However, the result is only valid if it follows the above rules (by applying the increment/decrement operator n times).
In all other cases, the result is undefined. So, more specifically :
>> pile.begin()+3-5
is undefined
>> pile.end()+5
is undefined (it might work if the past-the-end iterator is dereferenceable, but there's no guarantee)
So, on some platforms, it might work (depending on how the C++ standard is interpreted), but there's no guarantee.
For example, with gcc, the following code crashes :
You can only decrement an iterator if the resulting iterator would be dereferenceable.
past-the-end iterators are not guaranteed to be dereferenceable.
Since vector iterators are random access iterators, the operator+ and operator- are also defined for it, so you can add (or subtract) an integer value to (from) it. However, the result is only valid if it follows the above rules (by applying the increment/decrement operator n times).
In all other cases, the result is undefined. So, more specifically :
>> pile.begin()+3-5
is undefined
>> pile.end()+5
is undefined (it might work if the past-the-end iterator is dereferenceable, but there's no guarantee)
So, on some platforms, it might work (depending on how the C++ standard is interpreted), but there's no guarantee.
For example, with gcc, the following code crashes :
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> values;
std::vector<int>::iterator it = values.begin() - 1;
std::vector<int>::iterator it2 = values.end() + 1;
std::cout << *it << std::endl; // CRASH !!!
std::cout << *it2 << std::endl; // CRASH !!!
return 0;
}
wow, I must have been typing very slow lol. Sorry.
ASKER
Hm... That's a shame, thanks anyway. I was rather hoping to avoid having to check the bounds before doing it, but if that's the only way...
ASKER
Hehe, sorry Infinity - just a bit slow there. Thanks anyways mate. :)
Maybe I should have actually filled the vector with something heh. The fact that the following code doesn't crash is merely due to the implementation of iterators as gcc used. But again, there's no guarantee this code won't crash for another compiler.
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> values(5);
std::vector<int>::iterator it = values.begin() - 1;
std::vector<int>::iterator it2 = values.end() + 1;
std::cout << *it << std::endl; // no crash
std::cout << *it2 << std::endl; // no crash
return 0;
}
>> Hehe, sorry Infinity - just a bit slow there. Thanks anyways mate. :)
No worries ;) I'll have to be faster next time heh
No worries ;) I'll have to be faster next time heh