Vector of pointers

T

Timothee Groleau

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>?

To be specific, here is my situation, I have 2 classes A and B. Class A
contains a private vector of pointers to B objects and I need to sort this
vector after it is populated.

I was hoping to use <algorithm> sort along with an overloaded operator<
member function in B but that doesn't work with a vector of pointer.

Is it better to create a global compare function that deferences the
pointers or to create a static compare function in class A instead (since
the sorting will be done by class A only)?

I did some research and I also found this ptr_vector template:
http://www.codeproject.com/vcpp/stl/ptr_vecto.asp
which looks like it may do just what I need. Has anybody tried successfully
a similar approach before?

Thanks in advance!

Tim.
 
A

Axter

Timothee said:
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>?

To be specific, here is my situation, I have 2 classes A and B. Class A
contains a private vector of pointers to B objects and I need to sort this
vector after it is populated.

I was hoping to use <algorithm> sort along with an overloaded operator<
member function in B but that doesn't work with a vector of pointer.

Is it better to create a global compare function that deferences the
pointers or to create a static compare function in class A instead (since
the sorting will be done by class A only)?

I did some research and I also found this ptr_vector template:
http://www.codeproject.com/vcpp/stl/ptr_vecto.asp
which looks like it may do just what I need.

I recommend using a smart pointer that uses value semantics for
operator comparison.
The following smart pointer will do just that:
http://axter.com/smartptr

You can also use a more simplified version of the above smart pointer:
http://code.axter.com/copy_ptr.h
or
http://code.axter.com/cow_ptr.h

Both of these smart pointers will let you sort a vector of pointers
with the sort function sorting the pointee instead of the pointer
address.
Moreover, they both have a build-in clone function that will clone the
object without having to require that the pointee have a clone method.

If the ptr_vector class is anything like the boost pointer container, I
would recommend against it.
I found numerous problems with the boost pointer of containers, that
you would not have if you use a standard STL container of clone smart
pointers.
For example, there's no copy constructor or assignment operator for
ptr_vector.
 
R

Roland Pibinger

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>?

You've chosen the most difficult part of C++ for your begin.
To be specific, here is my situation, I have 2 classes A and B. Class A
contains a private vector of pointers to B objects and I need to sort this
vector after it is populated.

I was hoping to use <algorithm> sort along with an overloaded operator<
member function in B but that doesn't work with a vector of pointer.

'member function' is the problem
Is it better to create a global compare function that deferences the
pointers or to create a static compare function in class A instead (since
the sorting will be done by class A only)?

..... or a compare object. Those solutions 'work' if your function
compares pointed-to objects, not pointers. But the overall handling of
pointers in 'Standard' Standard containers remains highly
unsatisfactory.
I did some research and I also found this ptr_vector template:
http://www.codeproject.com/vcpp/stl/ptr_vecto.asp
which looks like it may do just what I need. Has anybody tried successfully
a similar approach before?

To the best of my knowledge this is the only STL-compliant container
for pointers available online. You can find other solutions,
vendor-specific as well as "smart" containers that intermingle
container functionality and object lifetime management. But if you
look for a pure STL-container for pointers and nothing else then I
know of no altervative.
ptr_vector should be usable out of the box (it's one header file with
no dependencies to third-party libraries). With the included unit
tests you can quickly check if ptr_vector compiles and runs on your
platform. The unit tests also give you hints how to use some of the
functions. You can reach me by email if something doesn't work as
expected.
Maybe you can also compare ptr_vector to other solutions (e.g. "smart"
pointers) WRT usability and interface consistency (at least I would be
interested in first-hand user experience).

To sort the container you just need to write (if MyClass has defined
an operator< )

ptr_vector<MyClass> pv;
// ...
pv.sort();
// or
stdx::sort (pv.begin(), pv.end()); // note: namespace stdx
// or
stdx::stable_sort (pv.begin(), pv.end());

Best wishes,
Roland Pibinger
 
A

Axter

Roland said:
You've chosen the most difficult part of C++ for your begin.


'member function' is the problem


.... or a compare object. Those solutions 'work' if your function
compares pointed-to objects, not pointers. But the overall handling of
pointers in 'Standard' Standard containers remains highly
unsatisfactory.


To the best of my knowledge this is the only STL-compliant container
for pointers available online.
ptr_vector is not an STL-compliant container.
Moreover, boost has this container avaiable, and I would recommend
using the boost version instread of the CodeProject version, since it's
more likely to have better peer review.
look for a pure STL-container for pointers and nothing else then I
know of no altervative.

An STL container of smart pointers, like that in the following link,
would be more compatible to STL containers then that of ptr_vector
container.
http://axter.com/smartptr
 
R

Roland Pibinger

ptr_vector is not an STL-compliant container.

It is. What should be not STL-compliant? ptr_vector fulfills the
requirements of a STL container and the interators work with
std::algorithms.
Moreover, boost has this container avaiable, and I would recommend
using the boost version instread of the CodeProject version, since it's
more likely to have better peer review.

Have you reviewed it? Moreover, the boost pointer containers are not
primarily containers but object managers that own and 'clone' objects.
They have totally different semantics compared to my solution.
An STL container of smart pointers, like that in the following link,
would be more compatible to STL containers then that of ptr_vector
container.
http://axter.com/smartptr

"Smart" pointer interfaces imitate real pointers. Combined with
std::containers they produce the same questionable result. But, as
I've said before, everyone can compare ptr_vector to other solutions
WRT usability and interface consistency and derive his/her own
conclusions.

Best wishes,
Roland Pibinger
 
A

Alan Johnson

Roland said:
It is. What should be not STL-compliant? ptr_vector fulfills the
requirements of a STL container and the interators work with
std::algorithms.


Have you reviewed it? Moreover, the boost pointer containers are not
primarily containers but object managers that own and 'clone' objects.
They have totally different semantics compared to my solution.


"Smart" pointer interfaces imitate real pointers. Combined with
std::containers they produce the same questionable result. But, as
I've said before, everyone can compare ptr_vector to other solutions
WRT usability and interface consistency and derive his/her own
conclusions.

Best wishes,
Roland Pibinger

Looking at your ptr_vector implementation, I think one of your examples
is not exception-safe:

void myFunc()
{
ptr_vector<string> ptv;
ptr_vector_owner<string> owner (ptv);

ptv.push_back (new string ("Once upon a time ...")); // LOOK HERE!!!
// ...

if (something.isWrong())
throw exception ("something real wrong!");
// ...

return;
} // pointed-to objects in ptv are deleted here!



Look at the line I labeled "LOOK HERE!!!". push_back can throw an
exception, at which point the string you allocated with new never gets
deleted. To safely push_back a pointer to a dynamically created object
you'd have to do something like:

auto_ptr<string> p = new string ("Once upon a time ...")
ptv.push_back (p.get());
p.release();


Alan
 
R

Roland Pibinger

Looking at your ptr_vector implementation, I think one of your examples
is not exception-safe: ....
Look at the line I labeled "LOOK HERE!!!". push_back can throw an
exception, at which point the string you allocated with new never gets
deleted.

First, ptr_vector does _not_ construct, copy, assign, clone, or
destroy any pointed-to objects. It simply doesn't 'own' the pointed-to
objects. This is a feature not a liability. ptr_vector can contain
static, stack- and heap-objects, even mixed. ptr_vector member
functions provide either the no-throw or the strong exception
guarantee. As one simple way to manage heap objects I describe a small
helper class template called ptr_vector_owner. There exist other
possibilities to control the lifetime of heap objects. What you call
'not exception-safe' is the OOM (Out-Of-Memory) situation. In general,
OOM is a fatal error. You cannot (can hardly) handle OOM with
exception handling ( see e.g. Herb Sutter's article
http://www.gotw.ca/publications/mill16.htm ). The helper template
solution is appropriate for any practical purpose (you can find
'OOM-unsafe' code in Stroustrup's and Josuttis' book). If you really
need more and(!) want to use the simple helper template you may write
something like:

// as above
ptv.reserve(ptv.size() < ptv.capacity() ? ptv.size(): ptv.size()*2);
ptv.push_back ( new string ("..."));

But the important thing is ptr_vector itself, not the accessory part.

Best wishes,
Roland Pibinger
 
A

Axter

Roland said:
It is. What should be not STL-compliant? ptr_vector fulfills the
requirements of a STL container and the interators work with
std::algorithms.

Just look at the member function overview, on the link.
STL containers are copiable and assignable. ptr_vector is not.
A vector can be resize, and ptr_vector can not.
ptr_vector does not support erase(), clear(), nor assign().
If you use a std::vector of smart pointers, the container would be
copiable, assignable, and support resize(), clear(), assign(), and
erase().
You would have a much more STL-compatible container with
std::vector<smart_ptr<T> >, then you would with ptr_vector<T>

Since ptr_vector doesn't own the poitners, I don't see the benifit in
not supporting a copy constructor and/or operator=() for ptr_vector.

I also prefer using logic in which the pointer is manged automatically.
IMHO, ptr_vector is similar to using raw pointers, in which there's no
pointer control.
Which means you could be using an object that has had early deletion,
or you could end up with objects that never get deleted at all.

To get better pointer management and a more compatible STL-container, I
recommend using a STL container of smart pointers over ptr_vector.

----------------------------------------------------------------------------------------
David Maisonave
http://axter.com

Author of Axter's policy based smart pointers
(http://axter.com/smartptr)
Top ten member of C++ Expert Exchange:
http://www.experts-exchange.com/Cplusplus
----------------------------------------------------------------------------------------
 
F

Fei Liu

Timothee said:
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>?

To be specific, here is my situation, I have 2 classes A and B. Class A
contains a private vector of pointers to B objects and I need to sort this
vector after it is populated.

I was hoping to use <algorithm> sort along with an overloaded operator<
member function in B but that doesn't work with a vector of pointer.

Turn this operator < into a non-member function, and you will be able
to get everything work without a lot of hassle...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,008
Messages
2,570,268
Members
46,867
Latest member
Lonny Petersen

Latest Threads

Top