Size_t Weird Bug within Loop
Hello to all expert,
Code:
vector<string> obj;
obj.push_back("asdas");
obj.push_back("fgh");
obj.push_back("vb");
obj.push_back("fgh");
obj.push_back("asdas");
obj.push_back("ljk");
for (size_t loop = obj.size() - 1;
loop>=0;--loop)
{
cout << obj[loop] << "\n";
}
The loop cout down from 5-4-3-2-1-0-4294967295(unsigned int loop). Then exception is thrown.
Minimum unsigned int(size_t) is 0.
Thanks.
Re: Size_t Weird Bug within Loop
Because your decrement loop is completely wrong. Try
Code:
for (size_t loop = obj.size(); loop--; )
{
...
}
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
Peter_APIIT
The loop cout down from 5-4-3-2-1-0-4294967295(unsigned int loop). Then exception is thrown.
How is this any different for any loop that uses unsigned counters?
The solution is simple -- don't write loops this way that rely on unsigned values to be valid and not wrap around.
Regards,
Paul McKenzie
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by Paul McKenzie
The solution is simple -- don't write loops this way that rely on unsigned values to be valid and not wrap around.
Yes, and an alternative would be to use reverse iterators obtained via rbegin() and rend(). In fact, in this case instead of a loop a simple application of std::copy would suffice, e.g.,
Code:
copy(obj.rbegin(), obj.rend(), ostream_iterator<string>(cout, "\n"));
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
PredicateNormative
Because your decrement loop is completely wrong. Try
Code:
for (size_t loop = obj.size(); loop--; )
{
...
}
:confused:
Re: Size_t Weird Bug within Loop
GCDEF,
While PredicateNormative's loop is "unusual" and I would definately recommend one of the other approaches, it does apper to be valid.
It will iterate the desired number of times, with loop containing a valid [but off by one] index. The last iteration of the loop, will cause the post decrement to leave loop in a poorly defined state (it will have wrapped), but there would be no access to the variable once it occured.
IMHO a :thumbd: on the approach, but I can't go as far as saying it is "wrong" (unless of course I am missing something.
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
TheCPUWizard
GCDEF,
While PredicateNormative's loop is "unusual" and I would definately recommend one of the other approaches, it does apper to be valid.
It will iterate the desired number of times, with loop containing a valid [but off by one] index. The last iteration of the loop, will cause the post decrement to leave loop in a poorly defined state (it will have wrapped), but there would be no access to the variable once it occured.
IMHO a :thumbd: on the approach, but I can't go as far as saying it is "wrong" (unless of course I am missing something.
Agreed that it's odd. If I must write a loop that breaks form like that, I tend to prefer writing it as a while-loop. I don't think anyone should have to take a second look at a for-loop to see what it does; they should be used for readability's sake, not for brevity.
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
TheCPUWizard
GCDEF,
While PredicateNormative's loop is "unusual" and I would definately recommend one of the other approaches, it does apper to be valid.
It will iterate the desired number of times, with loop containing a valid [but off by one] index. The last iteration of the loop, will cause the post decrement to leave loop in a poorly defined state (it will have wrapped), but there would be no access to the variable once it occured.
IMHO a :thumbd: on the approach, but I can't go as far as saying it is "wrong" (unless of course I am missing something.
I can see how it works, but his comment that the OPs loop was "completely wrong" was incorrect. What he offered instead, while it appears it would work, is certainly not the normal way of doing it and not immediately intuitive. The only thing "completely wrong" in the OP's code is his decision to use an unsigned counter.
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by Hermit
Agreed that it's odd. If I must write a loop that breaks form like that, I tend to prefer writing it as a while-loop. I don't think anyone should have to take a second look at a for-loop to see what it does; they should be used for readability's sake, not for brevity.
On the other hand, conveniently restricting the lifetime of the loop index to the loop with a for loop makes sense (consider TheCPUWizard's observation that "there would be no access to the variable once it occured").
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
laserlight
On the other hand, conveniently restricting the lifetime of the loop index to the loop with a for loop makes sense (consider TheCPUWizard's observation that "there would be no access to the variable once it occured").
A good point. Certainly one could limit the variable's scope with an extra pair of curly braces, but that would be a bit on the ugly side, and not something I can honestly say that I do. I had read TheCPUWizard's statement differently, by the way, thinking he was noting merely that the variable never contained an unexpected value within the scope of the loop.
Re: Size_t Weird Bug within Loop
I prefer to limit the counter scope.
Quote:
copy(obj.rbegin(), obj.rend(), ostream_iterator<string>(cout, "\n"));
Nice approach. Never think before.
Quote:
The last iteration of the loop, will cause the post decrement to leave loop in a poorly defined state (it will have wrapped), but there would be no access to the variable once it occured.
Why last iteration will be no access to the variable once invalid state occurred to the counter variable ?
Code:
size_t loop;
for (loop = obj.size();loop--;)
{
cout << obj[loop] << "\n";
}
loop = 0;
Quote:
The only thing "completely wrong" in the OP's code is his decision to use an unsigned counter.
Since the MF of size function return unsigned int, therefore i just use size_t to wipe out the warning. Any good approach ?
Thanks.
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
PredicateNormative
Because your decrement loop is completely wrong. Try
Code:
for (size_t loop = obj.size(); loop--; )
{
...
}
Hello PredicateNormative,
How are you?
that code is really a good case study for me.
and I'd like to know if what I found out is correct or incorrect.
the code works because decrement operator itself returns
a new value to be checked as a conditional statement,
and keeps on going till the value becomes to a number which can be converted to bool,
thus, stopping if the value is zero(false)
No?
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by Peter_APIIT
Why last iteration will be no access to the variable once invalid state occurred to the counter variable ?
The variable would be out of scope so it cannot be accessed. Despite stating that you "prefer to limit the counter scope", your new example does not do that, hence there will be access to the variable after the loop.
Quote:
Originally Posted by Peter_APIIT
Since the MF of size function return unsigned int, therefore i just use size_t to wipe out the warning. Any good approach ?
As I stated, I think reverse iterators are an appropriate solution here. If you really want to use an index, I suppose you could explicitly cast it to int or long.
Quote:
Originally Posted by potatoCode
that code is really a good case study for me.
and I'd like to know if what I found out is correct or incorrect.
the code works because decrement operator itself returns
a new value to be checked as a conditional statement,
and keeps on going till the value becomes to a number which can be converted to bool,
thus, stopping if the value is zero(false)
No?
That is part of the idea, but you should consider why post-decrement is correct but pre-decrement is not.
Re: Size_t Weird Bug within Loop
I have found your descussions about my loop curiously interesting.
I came across it when I was running performance tests on a compiler that I had to use a couple of years ago. We were struggling to get the required performance out of the application, and on that compiler, I found that decrement loops were faster than increment loops, and that particular decrement loop was the fastest of the lot (though it may not be on other compilers). Because it requires less key strokes, out of laziness, I just got use to using it to the point that I've got so familiar with it, that I forget that it is not a form that people will recognise straight away. I guess that is why I found the responses to it so interesting. I knew it was an uncommon form, but I didn't know it was that uncommon. Had I have realised, I would have used a more well known form - I didn't mean to throw an odd ball in there.
The loop is to my knowledge completely correct and valid. That said, I am a believer that in the phrase "Programs must be written for people to read, and only incidentally for machines to execute." and from that point, it would be better for me to use well known form. Besides, my initial reason for using the loop (optimisation on a specific compiler), is not a good reason to use that form for everything.
Re: Size_t Weird Bug within Loop
Quote:
Originally Posted by
potatoCode
Hello PredicateNormative,
How are you?
that code is really a good case study for me.
and I'd like to know if what I found out is correct or incorrect.
the code works because decrement operator itself returns
a new value to be checked as a conditional statement,
and keeps on going till the value becomes to a number which can be converted to bool,
thus, stopping if the value is zero(false)
No?
That's pretty much the idea, any non-zero value will evaluate to 'true' whereas zero will evaluate to 'false'. This form of loop effectively removes an expression to be evaluated from each loop cycle. That said, compilers are pretty clever, and might make a better optimisation of a well known loop form. So, although I stand by the correctness of the implementation, I do not claim that this form is good for performance, but if nothing else, it does save on key strokes. ;)