Thanks alot guys this has helped a great deal! much appreciated
Thanks alot guys this has helped a great deal! much appreciated
Btw, for anyone interested, here's what I get with the undefined code:
Inserting
5
10
-33686019
0
459177
Printing
458760
What I find curious is this:
cout<<v[0]<<endl<<v[1]<<endl<<v[2]<<endl<<v[3]<<endl<<v[4]<<endl;
cout<<"Printing"<<endl;
cout<<v[4]<<endl;//v[4] has a value and its being printed which means [] operator has inserted it
It prints the same element twice, yet got different results.
And I suggest that anyone who thinks it is NOT undefined code, takes a look inside the ACTUAL code for vector.
I took a look at the code and it looks like this:
_Myfirst is a pointer of type int*. Does that insert a value?Code:reference operator[](size_type _Pos) { // subscript mutable sequence #if _HAS_ITERATOR_DEBUGGING if (size() <= _Pos) { _DEBUG_ERROR("vector subscript out of range"); _SCL_SECURE_OUT_OF_RANGE; } #endif /* _HAS_ITERATOR_DEBUGGING */ _SCL_SECURE_VALIDATE_RANGE(_Pos < size()); return (*(_Myfirst + _Pos)); }
If it does, then I don't see how.
Blam! Rumor smashed. Operator [] does not insert.
Oh, look. This crashes for me. I'm shocked. I'm also being sarcastic.Code:#include <iostream> #include <vector> int main() { std::vector<std::string> v; //v.resize(1001); v[1000] = "Some random string."; std::cout << "v[1000] = " << v[1000] << std::endl; return 0; }
If it's not undefined, why does it crash?
>> I see little benefit in using at() since it obviously has more overhead.
This would be a premature optimization, IMO, at least in most programs.
>> The error message is not vague and the error is easy to fix.
It's undefined behavior. The OP got lucky with an easy to understand error message because of his or her platform (which is probably doing range-checking on operator[] anyway meaning at() adds no overhead). It might appear to work but give incorrect data to your program, which is why I suggested that at() be considered.
>> according to the original Code from te5la which uses break means he want to remove the
>> first only so It doesnt need to care about all other matches.
noobcpp, your iterator example did not break when it found a match, so either it is wrong because it doesn't follow the OP's use case or it is wrong because it fails to delete all values. Either way it is wrong (in fact, it could lead to accessing an iterator after end() which is also quite bad).
And as has been noted vector does not insert when you use operator[] (although std::map does). Please be careful to not give such blatantly wrong information in the future, it can be very confusing for the person just looking for a simple answer.
Well.... to give new input to this passionate discussion: let's have a look at the "vector" header file! It's open source, so you can just look it up. (please do so, noobcpp!).
(ps: this also should be stated in the Doxygen documentation of STL)Code:// element access /** * @brief Subscript access to the data contained in the %vector. * @param n The index of the element for which data should be * accessed. * @return Read/write reference to data. * * This operator allows for easy, array-style, data access. * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) */ reference operator[](size_type __n) { return *(this->_M_impl._M_start + __n); } /** * @brief Subscript access to the data contained in the %vector. * @param n The index of the element for which data should be * accessed. * @return Read-only (constant) reference to data. * * This operator allows for easy, array-style, data access. * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) */ const_reference operator[](size_type __n) const { return *(this->_M_impl._M_start + __n); }
And this is what "at()" does:
And finally, tratatatata............ the function "at()" :Code:/// Safety check used only from at(). void _M_range_check(size_type __n) const { if (__n >= this->size()) __throw_out_of_range(__N("vector::_M_range_check")); }
Now guess what: "reference" and "const_reference" are typedefs for allocators:Code:/** * @brief Provides access to the data contained in the %vector. * @param n The index of the element for which data should be * accessed. * @return Read/write reference to data. * @throw std::out_of_range If @a n is an invalid index. * * This function provides for safer data access. The parameter * is first checked that it is in the range of the vector. The * function throws out_of_range if the check fails. */ reference at(size_type __n) { _M_range_check(__n); return (*this)[__n]; } /** * @brief Provides access to the data contained in the %vector. * @param n The index of the element for which data should be * accessed. * @return Read-only (constant) reference to data. * @throw std::out_of_range If @a n is an invalid index. * * This function provides for safer data access. The parameter * is first checked that it is in the range of the vector. The * function throws out_of_range if the check fails. */ const_reference at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; }
which means simply that one can write an element with the function "at()" (again erroneous information, noobcpp!)Code:typedef typename _Tp_alloc_type::reference reference;
ps: Isn't this poetry at it's most beautiful... :-)
>> let's have a look at the "vector" header file
Of course, that's just one implementation. The final say is the standard, but this is such a simple and obvious point that everybody but noobcpp agrees on that I don't plan to look up the relevant text.
Yes after posting that I realized this argument was not the best and it's not exactly what I was trying to say. By no means would extra at()'s hurt performance and not all apps even care about top performance. So I will certainly retract this statement and restate it as - I prefer to use array access but probably have no good reason for doing so other than pure habit.>> I see little benefit in using at() since it obviously has more overhead.
This would be a premature optimization, IMO, at least in most programs.
I think my point was the root of the problem was not necessarily the use of the array access operator but it was the misuse of it - IE: using it with an out of bounds index. Using at() would ensure you were in-bounds but I guess I'm coming from the mindset of you should know if you are in bounds or not. So the bottom line is this is a complete misuse of size() and of vector. I also don't want to project the notion that using at() is more valid than using array access or vice versa b/c both those arguments are quite absurd. It comes down to a choice on the programmer's part and if he/she uses their chosen method correctly they should have no troubles. I am certainly not condoning the use of code that produces undefined behavior. In the end I think most of us, minus a few, are saying the same thing.>> The error message is not vague and the error is easy to fix.
It's undefined behavior. The OP got lucky with an easy to understand error message because of his or her platform (which is probably doing range-checking on operator[] anyway meaning at() adds no overhead). It might appear to work but give incorrect data to your program, which is why I suggested that at() be considered.
Last edited by VirtualAce; 07-15-2008 at 08:43 PM.
I dont want to argue
Its a vector not a Map so it must mantain a sequence and when 0, 1, 2 ..... is not present you cnt insert an element on 1000 so it crashed.
it can also happen that it crashed cause it tried to insert but failed.
PLESE READ THE FULL POST
But in most of the cases it inserts or at least it tries to insert. If one is stuck to say undefined behaviour Cant we put
"trying to inserting an Item and failing" and
"successfully Inserting an Item" and
"Wrongly inserting an Item" and
"inserting 0" and
"inserting junk" and
"crashing if jumped too far away indexes"
all this posibilities together in the list of undefined behaviours ??
However in vector its numarically and sequentialy indexed where as in map its not and in case of map's operator[]() it inserts a new element on the non existing node. (which is stated in documentation)
and so in case vector also it tries to insert which leads undefined befaviour
noobcpp: Just on the off hand that yet one more pseron telling you that you are wrong will make a difference:
The [] operator for a vector does not insert - EVER!!!
The [] operator for a map does insert if the item does not already exist.
The push_back method for a vector will insert one more item at the end of the vector.
If you don't want to argue then stop posting nonsense. Of course people will disagree with false statements. It's in your best interests to do some research, realise you were wrong, swallow your pride, and actually learn something. That is if you'd perfer to stop making yourself look stupid.
Last edited by iMalc; 07-16-2008 at 12:47 AM.
My homepage
Advice: Take only as directed - If symptoms persist, please see your debugger
Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"
Again, vector does not insert. Ever.
We have showed you two possible implementations, of which neither tried to insert anything.
The standard says it's undefined, because access an out-of-bounds element is undefined.
On other other hand, Microsoft's code also looks for out-of-range and throws or raises an assert if out-of-bounds happens because the standard does not say what happens if you do out of bounds.
However, if you think that operator [] will insert, you are fatefully mistaken. We will most likely (99% sure) that we will NEVER see such an implementation.
It tries to access an out-of-bounds element, which leads to undefined behavior. That's all.
>> I guess I'm coming from the mindset of you should know if you are in bounds or not.
Understood. I honestly don't use at() myself. However, for someone having trouble knowing if they are in bounds or not, then it can be a good tool with few (if any) drawbacks. I think ideally I would move to using at() myself for non-performance critical operations, but I'm too stuck in the C style array habit to make the change.