Boost logo

Boost :

Subject: Re: [boost] Dereferencing End Iterators (Was: Performance Tuning?)
From: Stewart, Robert (Robert.Stewart_at_[hidden])
Date: 2009-07-22 08:12:05

Edward Grace wrote:
> On 21 Jul 2009, at 13:42, Celtic Minstrel wrote:
> > On Tue, Jul 21, 2009 at 6:17 AM, Edward
> > Grace<ej.grace_at_[hidden]> wrote:
> > The standard does not require bounds checking on array
> > subscript, though it seems there's nothing saying it
> > shouldn't bounds check. But there's the alternate
> > notation if you do need bounds checking.
> My problem is really that this is 'undefined' behaviour.
> Surely anything that's 'undefined' is open to error?
> My second gripe is that even the idea of undefined behaviour is
> inconsistent (in MSVC at least). I can quite happily iterate
> something to .end() (one past the last element) but not to
> .end()+n --- why?

Because dereferencing an end iterator has undefined behavior.

> From what I understand dereferencing either is wrong, why is
> one more wrong than the other?

It isn't more wrong. The effects are simply more pronounced for
one than the other due to some implementation detail on which you
cannot count.

> From what I can see this prevents the simple creation of a
> striding iterator, for which the .end() can be at .end() +
> stride of the underlying vector. One can do it easily by
> default in g++ as it doesn't hold your hand (exposing you to
> dereferincing this as being undefined) and leaving that up to
> you. In MSVC8 it will barf since the debug bounds checking
> doesn't allow you to keep iterating past the end.

The debug bounds checking is revealing that you are relying on
undefined behavior.

> Which is the correct treatment?

Perhaps you're unfamiliar with the phrase "undefined behavior."
It means that absolutely anything is possible. Each
implementation can behave differently, even in different cases.
If you avoid doing what has undefined behavior, you'll never
encounter such vagaries. If you persist in doing what has
undefined behavior, you'll need to account for the differences
among compilers -- across versions and operating systems -- and
any use cases that lead to different results. Furthermore, you'd
have to maintain the non-portable code as each new compiler or
use cases presents.

If it isn't clear by now, don't dereference an end iterator and
don't try to dereference anything past it. Doing so is
untenable in portable code.

Rob Stewart robert.stewart_at_[hidden]
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Boost list run by bdawes at, gregod at, cpdaniel at, john at