473,379 Members | 1,243 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,379 software developers and data experts.

An STL vector collection of C++ interface pointers?

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
8 4999
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

"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
"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
"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
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
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
"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
"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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

20
by: Hanzo | last post by:
I'm iterating over a vector of base class pointers and deleting those which meet a certain criteria...i'm using pretty text-book code for the particular delete/erasure (it's straight out of Myers'...
9
by: luigi | last post by:
Hi, I am trying to speed up the perfomance of stl vector by allocating/deallocating blocks of memory manually. one version of the code crashes when I try to free the memory. The other version...
11
by: ma740988 | last post by:
Consider a class - lets call it CObjectHolderClass that has a collection of object pointers like std::vector<CBaseClass*> base_class_vec; as member var. Now somewhere in my CObjectHolderClass...
34
by: Adam Hartshorne | last post by:
Hi All, I have the following problem, and I would be extremely grateful if somebody would be kind enough to suggest an efficient solution to it. I create an instance of a Class A, and...
8
by: Ross A. Finlayson | last post by:
I'm trying to write some C code, but I want to use C++'s std::vector. Indeed, if the code is compiled as C++, I want the container to actually be std::vector, in this case of a collection of value...
9
by: Timothee Groleau | last post by:
Hi all, My name is Tim, I'm just getting started with C++ and this is my first post to the group. Is there a standard recommended approach to use a vector of pointers along with <algorithm>?...
5
by: Gert Van den Eynde | last post by:
Hi all, It's probably trivial but I can't figure it out... I have a templated class template <typename T, typename uclass A I wish to fill a vector with pointers to objects of class A. I...
6
by: lokchan | last post by:
i want to create a vector of pointer s.t. it can handle new and delete but also have std::vector interface can i implement by partial specialization and inherence like follow ? #include...
4
by: Christian Schmidt | last post by:
Hi all, I'm trying to implement a std::vector-like wrapper for IList. The hard part seems to be operator, because it returns an unmanaged reference. Probably I have to use pin_ptr to achieve this,...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.