By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,183 Members | 1,212 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,183 IT Pros & Developers. It's quick & easy.

An STL vector collection of C++ interface pointers?

P: n/a
Hi,

I've developed a class that implements an interface definition. It looks
like this:

class IRecord {
public:
// define interface methods by pure virtual methods
// no member variables
}
class CRecord : public IRecord {
public:
// implement interface methods
}

Now, I'm creating a collection of the interface pointers using:
std::vector<IRecord*> vRecPtrs; The following code is used to create a
series of interface pointers and push them into the vector:

std::vector<IRecord*> vRecPtrs;
vRecPtrs.resize (vRecPtrs.size()+1);
vRecPtrs[vRecPtrs.size()-1] = (IRecord*) new CRecord();
// well, I do have to resize the vector to get a new position before I can
create the new interface instance in my actual case. I can't use
vector::insert, nor vector::push_back.

So I pushed 100 instances to the vector. I iterate through all of them,
calling their methods, and they turned out fine.

However, something will screw up after I call vector::erase. In a case, I
have to remove an item from the collection, say:

delete vRecPtrs[10];
vRecPtrs.erase(vRecPtrs.begin()+10);

The 10th instance will be removed successfully. But the last item
(vRecPtrs.size()-1) will no longer be a valid pointer. Accessing any methods
of the last item will result in an access violation reading crash. I checked
the the pointer value of the last item through debuggers, and it does look
like a real pointer. Its value is expected, and does look like others. But
why can't I use it anymore? Why is the last item? Should I use some "safer
vector" for pointers?

Thanks
--
He Shiming
Aug 4 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
He Shiming wrote:
I've developed a class that implements an interface definition. It looks
like this:

class IRecord {
public:
// define interface methods by pure virtual methods
// no member variables
}
class CRecord : public IRecord {
public:
// implement interface methods
}

Now, I'm creating a collection of the interface pointers using:
std::vector<IRecord*> vRecPtrs; The following code is used to create a
series of interface pointers and push them into the vector:

std::vector<IRecord*> vRecPtrs;
vRecPtrs.resize (vRecPtrs.size()+1);
Here you essentially say

vRecPtrs.resize(1);

because the size is 0 when a vector is default-initialised.
vRecPtrs[vRecPtrs.size()-1] = (IRecord*) new CRecord();
There is no need to cast it. There is an implicit conversion from
a pointer to CRecord to a pointer to IRecord. Try to get into habit
of _avoiding_ C-style casts at all costs (pun intended).
// well, I do have to resize the vector to get a new position before I can
create the new interface instance in my actual case. I can't use
vector::insert, nor vector::push_back.
Why can't you?
So I pushed 100 instances to the vector. I iterate through all of them,
calling their methods, and they turned out fine.

However, something will screw up after I call vector::erase. In a case, I
have to remove an item from the collection, say:

delete vRecPtrs[10];
vRecPtrs.erase(vRecPtrs.begin()+10);

The 10th instance will be removed successfully. But the last item
(vRecPtrs.size()-1) will no longer be a valid pointer.
What does that mean?
Accessing any methods
of the last item will result in an access violation reading crash.
Are you hanging onto a reference to that element in the vector?
I checked
the the pointer value of the last item through debuggers, and it does look
like a real pointer. Its value is expected, and does look like others. But
why can't I use it anymore? Why is the last item? Should I use some "safer
vector" for pointers?


No. You need to realise that if you remove something from a vector, all
iterators and references to the elements at and after that position in the
vector become _invalid_.

I am guessing here, of course. If you need real help from this newsgroup,
post your real code.

V
Aug 4 '05 #2

P: n/a

"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote in message
news:dc**********@news.yaako.com...
Hi,

I've developed a class that implements an interface definition. It looks
like this:

class IRecord {
public:
// define interface methods by pure virtual methods
// no member variables
}
class CRecord : public IRecord {
public:
// implement interface methods
}

Now, I'm creating a collection of the interface pointers using:
std::vector<IRecord*> vRecPtrs; The following code is used to create a
series of interface pointers and push them into the vector:

std::vector<IRecord*> vRecPtrs;
vRecPtrs.resize (vRecPtrs.size()+1);
vRecPtrs[vRecPtrs.size()-1] = (IRecord*) new CRecord();
// well, I do have to resize the vector to get a new position before I can
create the new interface instance in my actual case. I can't use
vector::insert, nor vector::push_back.

So I pushed 100 instances to the vector. I iterate through all of them,
calling their methods, and they turned out fine.

However, something will screw up after I call vector::erase. In a case, I
have to remove an item from the collection, say:

delete vRecPtrs[10];
vRecPtrs.erase(vRecPtrs.begin()+10);

The 10th instance will be removed successfully. But the last item
(vRecPtrs.size()-1) will no longer be a valid pointer. Accessing any
methods of the last item will result in an access violation reading crash.
I checked the the pointer value of the last item through debuggers, and it
does look like a real pointer. Its value is expected, and does look like
others. But why can't I use it anymore? Why is the last item? Should I use
some "safer vector" for pointers?


The object type is not the issue, but the fact that when you 'erase'
an elements from a vector, any iterators pointing to it or any elements
after it (i.e. with higher subscripts), become invalid. This is the way
vectors work. One container type you might consider is a 'std::list',
which when an element is erased, only any iterators pointing to the erased
element will be invalidated, any others will remain valid. Otherwise if you
insist upon staying with the vector, you'll need to devise some way of
restoring
any iterators invalidated by an erase operation.

Book recommendation: www.josuttis.com/libbook

-Mike
Aug 4 '05 #3

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:z%******************@newsread1.mlpsca01.us.to .verio.net...
He Shiming wrote:
I've developed a class that implements an interface definition. It looks
like this:

class IRecord {
public:
// define interface methods by pure virtual methods
// no member variables
}
class CRecord : public IRecord {
public:
// implement interface methods
}

Now, I'm creating a collection of the interface pointers using:
std::vector<IRecord*> vRecPtrs; The following code is used to create a
series of interface pointers and push them into the vector:

std::vector<IRecord*> vRecPtrs;
vRecPtrs.resize (vRecPtrs.size()+1);


Here you essentially say

vRecPtrs.resize(1);

because the size is 0 when a vector is default-initialised.
vRecPtrs[vRecPtrs.size()-1] = (IRecord*) new CRecord();


There is no need to cast it. There is an implicit conversion from
a pointer to CRecord to a pointer to IRecord. Try to get into habit
of _avoiding_ C-style casts at all costs (pun intended).
// well, I do have to resize the vector to get a new position before I
can create the new interface instance in my actual case. I can't use
vector::insert, nor vector::push_back.


Why can't you?
So I pushed 100 instances to the vector. I iterate through all of them,
calling their methods, and they turned out fine.

However, something will screw up after I call vector::erase. In a case, I
have to remove an item from the collection, say:

delete vRecPtrs[10];
vRecPtrs.erase(vRecPtrs.begin()+10);

The 10th instance will be removed successfully. But the last item
(vRecPtrs.size()-1) will no longer be a valid pointer.


What does that mean?
Accessing any methods
of the last item will result in an access violation reading crash.


Are you hanging onto a reference to that element in the vector?
I checked
the the pointer value of the last item through debuggers, and it does
look like a real pointer. Its value is expected, and does look like
others. But why can't I use it anymore? Why is the last item? Should I
use some "safer vector" for pointers?


No. You need to realise that if you remove something from a vector, all
iterators and references to the elements at and after that position in the
vector become _invalid_.

I am guessing here, of course. If you need real help from this newsgroup,
post your real code.

V


I'm not referencing the old index of the elements of course.

I wouldn't call this fake code. The real code is as long as 5000 lines, and
I'm trying to simplify the problem.
Regards,
He Shiming
Aug 4 '05 #4

P: n/a
"Mike Wahler" <mk******@mkwahler.net> wrote in message
news:N2***************@newsread2.news.pas.earthlin k.net...

The object type is not the issue, but the fact that when you 'erase'
an elements from a vector, any iterators pointing to it or any elements
after it (i.e. with higher subscripts), become invalid. This is the way
vectors work. One container type you might consider is a 'std::list',
which when an element is erased, only any iterators pointing to the erased
element will be invalidated, any others will remain valid. Otherwise if
you
insist upon staying with the vector, you'll need to devise some way of
restoring
any iterators invalidated by an erase operation.

Book recommendation: www.josuttis.com/libbook

-Mike


I want random access to the contained elements. I would prefer using
vectors. However, I don't understand why iterators are preventing it from
working considering I'm not using any. It works like this:

vRecPtrs[99]->Method(); // vRecPtrs has 100 elements, and this call worked.
vRecPtrs.erase(vRecPtrs.begin()+10);
vRecPtrs[98]->Method(); // this one caused a crash.

Why is that related the iterators? Aren't the pointers the only thing I'm
keeping in this container?

Plus, if like you said, all iterators after it are being invalidated, why
only the last item didn't work?
Best regards,
He Shiming
Aug 4 '05 #5

P: n/a
He Shiming wrote:
[...]
I'm not referencing the old index of the elements of course.
If you're not using the index (old or new), then how you access the
elements?
I wouldn't call this fake code. The real code is as long as 5000 lines, and
I'm trying to simplify the problem.


Well, once you get it down to 100 lines, and still haven't found the cause
of your troubles, post it here _in_full_.

V
Aug 4 '05 #6

P: n/a
He Shiming wrote:
[...]
I want random access to the contained elements. I would prefer using
vectors. However, I don't understand why iterators are preventing it from
working considering I'm not using any. It works like this:

vRecPtrs[99]->Method(); // vRecPtrs has 100 elements, and this call worked.
vRecPtrs.erase(vRecPtrs.begin()+10);
vRecPtrs[98]->Method(); // this one caused a crash.
REALLY? The problem is not in the vector, then. It's somewhere else.
Why is that related the iterators? Aren't the pointers the only thing I'm
keeping in this container?
It doesn't seem related to the iterators.
Plus, if like you said, all iterators after it are being invalidated, why
only the last item didn't work?


There is no explanation. Can you trap the "crash" in the debugger and see
what causes it?

V
Aug 4 '05 #7

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:jv*******************@newsread1.mlpsca01.us.t o.verio.net...
He Shiming wrote:
[...]
I'm not referencing the old index of the elements of course.


If you're not using the index (old or new), then how you access the
elements?
I wouldn't call this fake code. The real code is as long as 5000 lines,
and I'm trying to simplify the problem.


Well, once you get it down to 100 lines, and still haven't found the cause
of your troubles, post it here _in_full_.

V


Okay I'll try.

Aug 4 '05 #8

P: n/a
"He Shiming" <mailbill(NOSPAM)@21cn.com.nospam> wrote in message
news:dc**********@news.yaako.com...


Well, I hate to say this but I have solve the problem in the code deduction
process. It turned out that it wasn't the fault of vector or pointers. It's
the smart pointer mechanism I'm using, which isn't covered in the content of
my question. Sorry for that.

Best regards,
He Shiming
Aug 4 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.