maps and constructors

H

Hicham Mouline

Hello,


I am attempting to design a class:


class C {
std::map<double, const A> ma;
std::map<double, const B> ma;
..
public:
C(...);
};


The keys in the 2 maps are always identical. So I could choose:


std::map<double, const std::pair<A,B> >
or
std::map<double, const std::pair<A,B>* >
(ps: AFAIK, using a const-ref for the pair is impossible, but possible with
some boost classes)


Q1:
Is there a difference in memory usage, access speed or code
readability between the top choice and bottom ones?

Q2:
Between the 2 bottom ones (storing the pair object in the map vs storing the
ptr)


Q3:
For users of class C, what sort of constructors should I offer?
C::C(const std::map<double, const std::pair<A,B>* >& )


Or, should I allow adding elements to the map after the object being
constructed?
C::add(double, const A&, const B&)

Rds,
 
V

Victor Bazarov

Hicham said:
Hello,


I am attempting to design a class:


class C {
std::map<double, const A> ma;
std::map<double, const B> ma;
.
public:
C(...);
};


The keys in the 2 maps are always identical. So I could choose:


std::map<double, const std::pair<A,B> >
or
std::map<double, const std::pair<A,B>* >
(ps: AFAIK, using a const-ref for the pair is impossible, but
possible with some boost classes)


Q1:
Is there a difference in memory usage, access speed or code
readability between the top choice and bottom ones?

There is no "bottom one" to speak of. What does the pointer
point to? Without knowing that, it's impossible to tell you
the difference in memory usage, performance, or anything else.
Q2:
Between the 2 bottom ones (storing the pair object in the map vs
storing the ptr)

Same story. You don't explain where the pointer comes from, how
can we tell the difference?
Q3:
For users of class C, what sort of constructors should I offer?
C::C(const std::map<double, const std::pair<A,B>* >& )

You should offer what the users want. Ask the users. Since
you should synchronize the 'maps' it would be preferred to add
both 'A' and 'B' at the same time. Whether the users are going
to want to create a 'C' object from a pre-defined 'std::map',
I am not sure. Isn't the fact that you store those in a map
a simple implementation detail? It shouldn't dictate the user
interface to your class, you know.
Or, should I allow adding elements to the map after the object being
constructed?
C::add(double, const A&, const B&)

That seems preferable.

The users might also have arrays of 'double', 'A', and 'B', from
which they might want you to create your 'C' object. Consider
offering

C::C(size_t N, double* keys, const A* v1, const B* v2);

and tell them to make sure those arrays should better have at
least N elements. Then create your map in a loop, for example.

V
 
C

coal

Hello,

I am attempting to design a class:

class C {
  std::map<double, const A> ma;
  std::map<double, const B> ma;
.
public:
  C(...);

};

The keys in the 2 maps are always identical. So I could choose:

std::map<double, const std::pair<A,B> >
or
std::map<double, const std::pair<A,B>* >
(ps: AFAIK, using a const-ref for the pair is impossible, but possible with
some boost classes)

Q1:
Is there a difference in memory usage, access speed or code
readability between the top choice and bottom ones?

Using one map would be more efficient and would avoid the
synchronization problems already mentioned. You might consider
using a rb_tree as well. I wrote about that once
http://www.seventy7.homelinux.net/rbtree

Brian Wood
Ebenezer Enterprises
 
E

Erik Wikström

Hello,


I am attempting to design a class:


class C {
std::map<double, const A> ma;
std::map<double, const B> ma;
.
public:
C(...);
};


The keys in the 2 maps are always identical. So I could choose:


std::map<double, const std::pair<A,B> >
or
std::map<double, const std::pair<A,B>* >
(ps: AFAIK, using a const-ref for the pair is impossible, but possible with
some boost classes)


Q1:
Is there a difference in memory usage, access speed or code
readability between the top choice and bottom ones?

Yes, if you use two maps you have to store the key twice, and when
retrieving items you have to do the lookup twice too. If you always
handle both A and B together there is not reason to keep them in
separate maps.

Consider also the implications on exception-safety, if you have two maps
and want to insert a new pair of A and B and you successfully insert the
A into its map but an exception is thrown when inserting B you must
remove the A from its map.
Q2:
Between the 2 bottom ones (storing the pair object in the map vs storing the
ptr)

Yes, at the very least you need the extra memory that is used to store
the pointers in addition to the space for the pair. Of course you might
be able to save memory using the pointer if multiple entries in the map
refer to the same pair of A and B.
Q3:
For users of class C, what sort of constructors should I offer?
C::C(const std::map<double, const std::pair<A,B>* >& )


Or, should I allow adding elements to the map after the object being
constructed?
C::add(double, const A&, const B&)

Depends on how you plan to use C, perhaps you should offer both?
 
A

Andrew Koenig

What are these consts doing here? The value type of a map is supposed to be
assignable.

std::map<double, std::pair<A, B> >

Why not?
 
H

Hicham Mouline

Andrew Koenig said:
What are these consts doing here? The value type of a map is supposed to
be assignable.
my mistake.
std::map<double, std::pair<A, B> >

Why not?
The const was my mistaken attempt to change the elements of the pair, ie. to
make the 2nd line of code
M[5.0] = std::pair<a1, b1>;
M[5.0].first = a2;
impossible
My point is to store the pairs in the map once, and then never change them
at a later stage.

The choice between std::map<double, std::pair<A, B> > and std::map<double,
const std::pair<A, B>* >:
With a million entries in the map, and if the pairs already exist elsewhere,
the non-ptr-version of the map would copy those
pairs, while the ptr version would store only a ptr to each pair. Here i
assume

sizeof( const std::pair<A, B>* ) < sizeof( std::pair<A, B> )
 
J

jkherciueh

Hicham said:
Andrew Koenig said:
What are these consts doing here? The value type of a map is supposed to
be assignable.
my mistake.
std::map<double, std::pair<A, B> >

Why not?
The const was my mistaken attempt to change the elements of the pair, ie.
to make the 2nd line of code
M[5.0] = std::pair<a1, b1>;
M[5.0].first = a2;
impossible
My point is to store the pairs in the map once, and then never change them
at a later stage.

Then, you should consider

typedef std::pair< A, B > EntryType;
std::vector< tripple< std::pair< double, EntryType > > the_table;

Once all entries are stored, just sort() by the double entry and then use
binary_search() to retrieve values.
The choice between std::map<double, std::pair<A, B> > and std::map<double,
const std::pair<A, B>* >:
With a million entries in the map, and if the pairs already exist
elsewhere, the non-ptr-version of the map would copy those
pairs, while the ptr version would store only a ptr to each pair. Here i
assume

sizeof( const std::pair<A, B>* ) < sizeof( std::pair<A, B> )


Best

Kai-Uwe Bux
 

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
473,994
Messages
2,570,223
Members
46,815
Latest member
treekmostly22

Latest Threads

Top