Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

STL vector changing size during iter. causing problems

0 views
Skip to first unread message

Hanzo

unread,
Mar 17, 2003, 11:15:01 AM3/17/03
to
I have a vector of base class pointers, of which I am pushing back
new'd derived class pointers during an interator, like so:

vector<CBase*>::iterator aIter;

for (aIter = agents.begin(); aIter != agents.end(); ++aIter) // agents
is vector<CBase*>
{
CBase* a = *aIter;
a->memberFunction() // in here, I push new'd derived pointers onto
agents. agents.size() changes!
}

What I am finding is that, as I iterate, eventually, *aIter becomes a
CBase* object (which is further confusing, since it is an abstract
class)...I should only ever see derived classes pushed onto "agents".

Is there some fundamental thing I have overlooked in the STL in
regards to iterating over a container while it changes size? (or that
contains pointers to derived classes?) The obvious conclusions can not
be reached (ie there is absolutely NO reference to a "CBase* var = new
CBase()" anywhere in my code, and it couldn't happen anyway, because
its an ABC. So..why then does "agents" eventually iterate to these
unknown, unusable CBase* pointers?

- Hanzo

Neil Butterworth

unread,
Mar 17, 2003, 11:20:58 AM3/17/03
to

"Hanzo" <ha...@milclan.com> wrote in message
news:5esb7vso9io4r43ra...@4ax.com...

> I have a vector of base class pointers, of which I am pushing back
> new'd derived class pointers during an interator, like so:
>
> vector<CBase*>::iterator aIter;
>
> for (aIter = agents.begin(); aIter != agents.end(); ++aIter) // agents
> is vector<CBase*>
> {
> CBase* a = *aIter;
> a->memberFunction() // in here, I push new'd derived pointers onto
> agents. agents.size() changes!
> }

Calling push_back() on a vector may invalidate any existing iterators for
that vector - you would appear to have undefined behaviour, but it's hard to
say without seeing some _real_ code that illustrates the problem.

NeilB


Ivan Vecerina

unread,
Mar 17, 2003, 11:40:26 AM3/17/03
to
"Hanzo" <ha...@milclan.com> wrote in message
news:5esb7vso9io4r43ra...@4ax.com...
| Is there some fundamental thing I have overlooked in the STL in
| regards to iterating over a container while it changes size?

No, but individual containers have restrictions.
With std::vector, any item insertion may invalidate all iterators
that refer to a container's elements. This can only be prevented
if you know the maximum size of the container and call
vector::reserver(maxSize) before creating the iterators.

Solutions to this include:
- using std::list instead of std::vector for your list of agents
- using an item index instead of iterators:
for( AgentsType::size_type i = 0 ; i != vector.size() ; ++i )

I hope this helps,
--
Ivan Vecerina, Dr. med. <> http://www.post1.com/~ivec
Soft Dev Manger, xitact <> http://www.xitact.com
Brainbench MVP for C++ <> http://www.brainbench.com

Andrew Koenig

unread,
Mar 17, 2003, 12:49:29 PM3/17/03
to
Hanzo> I have a vector of base class pointers, of which I am pushing back
Hanzo> new'd derived class pointers during an interator, like so:

Hanzo> vector<CBase*>::iterator aIter;

Hanzo> for (aIter = agents.begin(); aIter != agents.end(); ++aIter)
Hanzo> // agents is vector<CBase*>
Hanzo> {
Hanzo> CBase* a = *aIter;
Hanzo> a-> memberFunction() // in here, I push new'd derived pointers onto
Hanzo> // agents. agents.size() changes!
Hanzo> }

Hanzo> What I am finding is that, as I iterate, eventually, *aIter becomes a
Hanzo> CBase* object (which is further confusing, since it is an abstract
Hanzo> class)...I should only ever see derived classes pushed onto "agents".

Hanzo> Is there some fundamental thing I have overlooked in the STL in
Hanzo> regards to iterating over a container while it changes size?

Yes. If you append an element to a vector, and doing so causes the vector
to be reallocated, it invalidates all iterators that refer to vector
elements.

The easiest way to solve this problem is to use indices instead
of iterators in your loop:

vector<CBase*>::size_type aIndex;
for (aIndex = 0; aIndex != agents.size(); ++i) {
agents[i]->memberfunction();
}


--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

0 new messages