Strange for loop problem.

Hi all,
I'm not sure if this belongs here or the Windows forum more, but I'll have a go here.

I have a piece of code with a for loop that collects object pointers from a queue, and after using each removes it from the queue.

This loop won't be reached unless there is at least one object pointer in the queue:
1
2
3
4
5
6
for ( Object* pobjCurrentObject = qObjectPointers.front()
	; !qObjectPointers.empty()
	; pobjCurrentObject = qObjectPointers.front() ) 
{


	qObjectPointers.pop();
}


This works as expected when I compile it with the gcc toolset on Linux, but when I ported this to Windows (VC Express 2008), it choked on this for loop. While stepping through the code I found that after the queue was empty, when the for statement was executed (should be for the last time.) I was getting an assertion from the STL that an iterator couldn't be dereferenced.

Am I correct that after the queue is empty, the only part of the for loop construct that should be called is the 'empty()' call, and when it returns true, the 'pobjCurrentObject = qObjectPointers.front()' call shouldn't be executed?

If I'm wrong, can someone tell me why? If I'm right, can someone tell me why it is behaving like this on Windows?

The equivalent behavior with a 'while' loop works fine:
1
2
3
4
5
bool bQueueEmpty = qObjectPointers.empty();
while(bQueueEmpty == false) {
	Object* pobjCurrentObject = qObjectPointers.front();


	qObjectPointers.pop();

	bQueueEmpty = qObjectPointers.empty();
}


Thanks,

Jivan
Last edited on
Well, I would probably check the C++ Standard for how a for loop is supposed to be evaluated...it would depend on whether it only checks the middle line on the last run through, or if it tries to do the whole line...Btw, anyway have a link to the Standard? I keep getting garbage on the STL instead of the standard.
Ah! But that's not the equivalent behavior!
Giver a for
1
2
3
for (<a>;<b>;<c>){
	<d>
}

its equivalent while is
1
2
3
4
5
6
7
{
	<a>
	while (<b>){
		<d>
		<c>
	}
}

The problem is that the VC++ implementation of std::deque::front() seems to use an iterator to get said element. Of course, if the strucutre is empty, the dereference will fail and the program will crash.
You should put an if around the for. Alternatively, you can use the while you already have.
Yeah, the for loop won't work because front() cannot be called on an empty deque.

IMHO the clearest way to write the loop is

1
2
3
4
while( !qObjectPointers.empty() ) {
  // stuff
  qObjectPointers.pop();
}

given:
1
2
3
for (<a>;<b>;<c>){
	<d>
}


I understand that 'front()' can't be called on an empty queue. It should never be called on an empty queue though. As I mentioned, this for loop will only be reached if the queue has at least one element, making <a> safe. Once the queue is empty <c> should never be called.

I don't have a copy of the most recent standard, but I think it's fair to expect that the behavior of a for loop hasn't changed. Am I missing something?

jsmith:
The use of the loop in my program better fit the thought of a for loop, as I needed a one-time initialization, a check, and a change after each iteration. I changed it to a while loop with some extra housekeeping to make the code happy under both Windows and Linux, but I'd still like to understand why it wasn't working as initially written.

firedraco:
The current standard isn't published online. You can buy the current copy for $175 from ANSI, or $18 for a pdf version from:
http://webstore.ansi.org/ansidocstore/default.asp.
I've read rumors that there are formatting issues with the pdf version.

If you don't have a pressing need for the current standard, Stroustrup's website has some nice links, including the old draft standard.
http://www.research.att.com/~bs/C++.html
The 1998 version of the standard can be grabbed from here:
http://www.kuzbass.ru/docs/ansi_iso_iec_14882_1998.pdf
Unfortunately, I don't think either will give you insight into the STL.
Last edited on
Notice the equivalent while loop. See that the order of execution is abdc, not badc. front() will be executed before empty() always.
Ok helios,
Now I get it, thanks.

Topic archived. No new replies allowed.