473,396 Members | 1,599 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,396 software developers and data experts.

Accessing classes from standard containers

Hello,

I have some code that I'm working on, the problem isn't that it doesn't
work it's that it's too slow. I have a class that holds my homemade class
within an std::map, within an std::map. here is the declaration.

std::map<char, std::map<char, CWordFrequency> > baseMap;

Now I can assign a pointer to the inner map, but I cannot assign a
pointer to my class without actually copying the second map into memory. I'm
not sure but I think the operators I need to use are ".*" or "->*".

Can somebody point me in the right direction?

Here is the slow but working code fragment.

sequenceFrequencyMap = baseMap[base];
tempFrequency = sequenceFrequencyMap[sequence];

if (wordPosition > 0 && (wordPosition + 1) < (word.length() -
1)) {tempFrequency.incrementCountWithin();}
else if (wordPosition == 0)
{tempFrequency.incrementCountBeginning();}
else if ((wordPosition + 1) == word.length() - 1)
{tempFrequency.incrementCountEnd();}

sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;
Jul 22 '05 #1
11 1223
References are your friends here:

CWordFrequency &wf = baseMap[base][sequence];
if( ... )
{ wf.incrementCountWithin(); }
// etc.

Jul 22 '05 #2
Juicer_X wrote:
Hello,

I have some code that I'm working on, the problem isn't that it doesn't work it's that it's too slow.
First off, this small code fragment is a bit difficult to decipher
because it doesn't clearly define the types of all of the instance
variables. In the future, it might be helpful for you to show the
declarations of the variables being used, so that your question is a
bit more clear.
From the context of your posting, I can only assume that there are declarations similar to the ones below someplace in the code prior to
the block you shared:

std::map<char, CWordFrequency> sequenceFrequencyMap;
CWordFrequency tempfrequency;
char base;
char sequence;

My answer will rely on these assumptions...

Now there are quite a few things one could do to speed up the code.
First off, the statements:
sequenceFrequencyMap = baseMap[base];
tempFrequency = sequenceFrequencyMap[sequence];
create temporary instances of std::map<char, CWordFrequency> and
CWordFrequency, respectively, that you then perform operations on.
These are extremely costly and seemingly unecessary operations in this
case.

It would be wiser to simply obtain a reference to the CWordFrequency
object (via map::operator[]), and then call your incrementXXXX()
methods using this reference. Do do this, simply get rid of the lines
above, and replace each place you use 'tempFrequency' with
'baseMap[base][sequence]'

Since you will now be working with your embedded object directly, you
will have no need to re-insert a copy of it into your map, therefore
the code below will also be unnecessary. sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;


Again, the code above was creating unnecessary copies of large objects,
and thus slowly you down. After making these changes, your code should
be significantly faster, and look something like the following snippet:

std::map<char, std::map<char, CWordFrequency> > baseMap;
if (wordPosition > 0 &&
(wordPosition + 1) < (2 - 1)) {
baseMap[base][sequence].incrementCountWithin();
}
else if (wordPosition == 0) {
baseMap[base][sequence].incrementCountBeginning();
}
else if ((wordPosition + 1) == 2 - 1) {
baseMap[base][sequence].incrementCountEnd();
}

There is one more thing that should be noted...

Since the standard containers are allowed to arbitrarily make copies of
their entries, it is likely that using either raw or managed pointers
to your CWordFrequency objects within your maps would also increase
speed. That being said, it is a less obvious optimization, not knowing
what a CWordFrequency object is. In any case, I normally recommend it
for most anything but the most primitive types.
I hope this helps!

Michael Loritsch

Jul 22 '05 #3

Juicer_X wrote:
Hello,

I have some code that I'm working on, the problem isn't that it doesn't work it's that it's too slow. I have a class that holds my homemade class within an std::map, within an std::map. here is the declaration.

std::map<char, std::map<char, CWordFrequency> > baseMap;

Now I can assign a pointer to the inner map, but I cannot assign a pointer to my class without actually copying the second map into memory. I'm not sure but I think the operators I need to use are ".*" or "->*".
No. First, the address-of operator is &, and secondly, the only thing
you need to do is name the object.
Here is the slow but working code fragment.

sequenceFrequencyMap = baseMap[base];
tempFrequency = sequenceFrequencyMap[sequence];
That's not a pointer! You're copying the entire inner map out, and
then you copy your class out of that copy!
if (wordPosition > 0 && (wordPosition + 1) < (word.length() - 1)) {tempFrequency.incrementCountWithin();}
else if (wordPosition == 0)
{tempFrequency.incrementCountBeginning();}
else if ((wordPosition + 1) == word.length() - 1)
{tempFrequency.incrementCountEnd();}

sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;
Simple optimalization:
((wordPosition + 1) == word.length() - 1) ==
(wordPosition + 2 == word.length() )
Compiler probably can't do that, because it is unlikely to see
that no overflow can happen.

The /real/ solution is to use references (not pointers):

std::map<char, CWordFrequency>& sequenceFrequencyMap = baseMap[base];
CWordFrequency& tempFrequency = sequenceFrequencyMap[sequence];

This means you won't copy the objects, but modify them in place.
As a result, the copy-back step can also be skipped, i.e. no more
sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;

Regards,
Michiel Salters

Jul 22 '05 #4

Why don't you use find() (the one included with map) & iterators?
Here is an example of how to access the value of the nested map.
I'm using the fact that an iterator behaves as if it is a pointer. In
your case you might want to store the iterator

#include <map>
#include <iostream>

int main()
{
// create & fill example double map
std::map<char, std::map<char, int> > Test;
std::map<char, int> Test2;
Test2['b'] = 4;
Test2['c'] = 1;
Test['b'] = Test2;
Test2.clear();
Test2['b'] = 2;
Test['o'] = Test2;
// acess innermap value
std::cout << ((Test.find('o'))->second.find('b'))->second;
std::cout << ((Test.find('b'))->second.find('b'))->second;
std::cout << ((Test.find('b'))->second.find('c'))->second;
// output should be 241
getchar();
return 0;
}

Jul 22 '05 #5
Juicer_X wrote:
Hello,

I have some code that I'm working on, the problem isn't that it doesn't work it's that it's too slow.
First off, this small code fragment is a bit difficult to decipher
because it doesn't clearly define the types of all of the instance
variables. In the future, it might be helpful for you to show the
declarations of the variables being used, so that your question is a
bit more clear.
From the context of your posting, I can only assume that there are declarations similar to the ones below someplace in the code prior to
the block you shared:

std::map<char, CWordFrequency> sequenceFrequencyMap;
CWordFrequency tempfrequency;
char base;
char sequence;

My answer will rely on these assumptions...

Now there are quite a few things one could do to speed up the code.
First off, the statements:
sequenceFrequencyMap = baseMap[base];
tempFrequency = sequenceFrequencyMap[sequence];
create temporary instances of std::map<char, CWordFrequency> and
CWordFrequency, respectively, that you then perform operations on.
These are extremely costly and seemingly unecessary operations in this
case.

It would be wiser to simply obtain a reference to the CWordFrequency
object (via map::operator[]), and then call your incrementXXXX()
methods using this reference. Do do this, simply get rid of the lines
above, and replace each place you use 'tempFrequency' with
'baseMap[base][sequence]'

Since you will now be working with your embedded object directly, you
will have no need to re-insert a copy of it into your map, therefore
the code below will also be unnecessary. sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;


Again, the code above was creating unnecessary copies of large objects,
and thus slowly you down. After making these changes, your code should
be significantly faster, and look something like the following snippet:

std::map<char, std::map<char, CWordFrequency> > baseMap;
if (wordPosition > 0 &&
(wordPosition + 1) < (2 - 1)) {
baseMap[base][sequence].incrementCountWithin();
}
else if (wordPosition == 0) {
baseMap[base][sequence].incrementCountBeginning();
}
else if ((wordPosition + 1) == 2 - 1) {
baseMap[base][sequence].incrementCountEnd();
}

There is one more thing that should be noted...

Since the standard containers are allowed to arbitrarily make copies of
their contents, I would also recommend using either raw or managed
pointers to your CWordFrequency objects would likely also increase
speed. That being said, it is a less obvious optimization, not knowing
what a CWordFrequency object is. In any case, I recommend it for most
anything but the most primitive types.
I hope this helps!

Michael Loritsch

Jul 22 '05 #6

"msalters" <Mi*************@logicacmg.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...

Juicer_X wrote:
Hello,

I have some code that I'm working on, the problem isn't that it doesn't
work it's that it's too slow. I have a class that holds my homemade

class
within an std::map, within an std::map. here is the declaration.

std::map<char, std::map<char, CWordFrequency> > baseMap;

Now I can assign a pointer to the inner map, but I cannot assign

a
pointer to my class without actually copying the second map into

memory. I'm
not sure but I think the operators I need to use are ".*" or "->*".


No. First, the address-of operator is &, and secondly, the only thing
you need to do is name the object.
Here is the slow but working code fragment.

sequenceFrequencyMap = baseMap[base];
tempFrequency = sequenceFrequencyMap[sequence];


That's not a pointer! You're copying the entire inner map out, and
then you copy your class out of that copy!


Sorry, I recently revised this code and took the pointer refrences out
for simplification. But there was a pointer to the inner map.
if (wordPosition > 0 && (wordPosition + 1) < (word.length() -
1)) {tempFrequency.incrementCountWithin();}
else if (wordPosition == 0)
{tempFrequency.incrementCountBeginning();}
else if ((wordPosition + 1) == word.length() - 1)
{tempFrequency.incrementCountEnd();}

sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;


Simple optimalization:
((wordPosition + 1) == word.length() - 1) ==
(wordPosition + 2 == word.length() )
Compiler probably can't do that, because it is unlikely to see
that no overflow can happen.


I don't seem to understand how this speeds anything up? Could you please
explain?
The /real/ solution is to use references (not pointers):

std::map<char, CWordFrequency>& sequenceFrequencyMap = baseMap[base];
CWordFrequency& tempFrequency = sequenceFrequencyMap[sequence];
So which way is better This way is more verbose which I like and it
seems that it's doing pretty much the same as : CWordFrequency &wf =
baseMap[base][sequence];
This means you won't copy the objects, but modify them in place.
As a result, the copy-back step can also be skipped, i.e. no more
sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;

Regards,
Michiel Salters


Thank you for the info.
Jul 22 '05 #7

<lo******@gmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Juicer_X wrote:
Hello,

I have some code that I'm working on, the problem isn't that it doesn't
work it's that it's too slow.


First off, this small code fragment is a bit difficult to decipher
because it doesn't clearly define the types of all of the instance
variables. In the future, it might be helpful for you to show the
declarations of the variables being used, so that your question is a
bit more clear.

Sorry, I forgot all about the declarations.
From the context of your posting, I can only assume that there are

declarations similar to the ones below someplace in the code prior to
the block you shared:

std::map<char, CWordFrequency> sequenceFrequencyMap;
CWordFrequency tempfrequency;
char base;
char sequence;

My answer will rely on these assumptions...

Your assumptions are correct.
Now there are quite a few things one could do to speed up the code.
First off, the statements:
sequenceFrequencyMap = baseMap[base];
tempFrequency = sequenceFrequencyMap[sequence];
create temporary instances of std::map<char, CWordFrequency> and
CWordFrequency, respectively, that you then perform operations on.
These are extremely costly and seemingly unecessary operations in this
case.

See the problem is I knew that it's just that I really didn't know any
other way of getting it done.
It would be wiser to simply obtain a reference to the CWordFrequency
object (via map::operator[]), and then call your incrementXXXX()
Ihad no idea that you could use operator[] like a 2 dimensional array.
It makes sense now but I really thought that I couldn't do that.
methods using this reference. Do do this, simply get rid of the lines
above, and replace each place you use 'tempFrequency' with
'baseMap[base][sequence]'

Since you will now be working with your embedded object directly, you
will have no need to re-insert a copy of it into your map, therefore
the code below will also be unnecessary.
sequenceFrequencyMap[sequence] = tempFrequency;
baseMap[base] = sequenceFrequencyMap;


This was really annoying to put in, but I was glad when I was able to
get rid of it.
Again, the code above was creating unnecessary copies of large objects,
and thus slowly you down. After making these changes, your code should
be significantly faster, and look something like the following snippet:

std::map<char, std::map<char, CWordFrequency> > baseMap;
if (wordPosition > 0 &&
(wordPosition + 1) < (2 - 1)) {
baseMap[base][sequence].incrementCountWithin();
}
else if (wordPosition == 0) {
baseMap[base][sequence].incrementCountBeginning();
}
else if ((wordPosition + 1) == 2 - 1) {
baseMap[base][sequence].incrementCountEnd();
}

There is one more thing that should be noted...

Since the standard containers are allowed to arbitrarily make copies of
their entries, it is likely that using either raw or managed pointers
to your CWordFrequency objects within your maps would also increase
speed. That being said, it is a less obvious optimization, not knowing
what a CWordFrequency object is. In any case, I normally recommend it
for most anything but the most primitive types.
I hope this helps!

Michael Loritsch


Thank you, for all your help.
Jul 22 '05 #8

<ve*********@hotmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...

Why don't you use find() (the one included with map) & iterators?
The thing is that I tried find(), but what happens is that it doesn't
matter whether or not my key pairs have actually been in the map before
because they will be added when I come across them.
Here is an example of how to access the value of the nested map.
I'm using the fact that an iterator behaves as if it is a pointer. In
your case you might want to store the iterator

#include <map>
#include <iostream>

int main()
{
// create & fill example double map
std::map<char, std::map<char, int> > Test;
std::map<char, int> Test2;
Test2['b'] = 4;
Test2['c'] = 1;
Test['b'] = Test2;
Test2.clear();
Test2['b'] = 2;
Test['o'] = Test2;
// acess innermap value
std::cout << ((Test.find('o'))->second.find('b'))->second;
std::cout << ((Test.find('b'))->second.find('b'))->second;
std::cout << ((Test.find('b'))->second.find('c'))->second;
// output should be 241
getchar();
return 0;
}


Your implementation has given me an idea. I need to use find() for when
I make new words out of my character pairs. My code is hard to read so I
think I might borrow your solution.
Jul 22 '05 #9
Juicer_X wrote:
<ve*********@hotmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...

Why don't you use find() (the one included with map) & iterators?
The thing is that I tried find(), but what happens is that it

doesn't matter whether or not my key pairs have actually been in the map before because they will be added when I come across them.


I'm not sure what you mean by this. If you mean that you want to add
values that not yet exist Alexm has shown a solution that will do that.

If you mean that find() actually adds values that is not true, if the
value you are trying to find does not exist in the map you get the same
iterator as the one you get when you do end(). That is why I said that
you'd probably have to work with iterators to when using find()

Jul 22 '05 #10

<ve*********@hotmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Juicer_X wrote:
<ve*********@hotmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
>
> Why don't you use find() (the one included with map) & iterators?


The thing is that I tried find(), but what happens is that it

doesn't
matter whether or not my key pairs have actually been in the map

before
because they will be added when I come across them.


I'm not sure what you mean by this. If you mean that you want to add
values that not yet exist Alexm has shown a solution that will do that.

If you mean that find() actually adds values that is not true, if the
value you are trying to find does not exist in the map you get the same
iterator as the one you get when you do end(). That is why I said that
you'd probably have to work with iterators to when using find()


Sorry, I wrote that in a hurry. I did adopt alexm's code for loading the
map. Because I'm reading information from a file and assume that everything
is valid. I error check before my class member is called.

I tried to validate with find() in a previous attempt but found it more
efficient without it. (Thats why I do it with another class now).

Thanks for replying,

Brent Ritchie
Jul 22 '05 #11
ve*********@hotmail.com wrote:
Why don't you use find() (the one included with map) & iterators?
Here is an example of how to access the value of the nested map.
I'm using the fact that an iterator behaves as if it is a pointer. In
your case you might want to store the iterator

#include <map>
#include <iostream>

int main()
{
// create & fill example double map
std::map<char, std::map<char, int> > Test;
std::map<char, int> Test2;
Test2['b'] = 4;
Test2['c'] = 1;
Test['b'] = Test2;
Test2.clear();
Test2['b'] = 2;
Test['o'] = Test2;
// acess innermap value
std::cout << ((Test.find('o'))->second.find('b'))->second;
std::cout << ((Test.find('b'))->second.find('b'))->second;
std::cout << ((Test.find('b'))->second.find('c'))->second;
// output should be 241
getchar();
return 0;
}


It appears the OP is only operating on individual items, rather than on an
entire inner map. An alternative that may be more efficient would be to
avoid the 'nested' maps and use a slightly more complex key in a single map.
Something like this:

int main()
{
typedef std::pair< char, char > tKey
typedef std::map < tKey, int > tMap;

tMap lMap;

lMap[tKey('o','b') ] = 1;
lMap[tKey('b','b') ] = 3;
lMap[tKey('b','c') ] = 5;

std::cout << lMap.find(tKey('o','b'))->second
<< lMap.find(tKey('b','b'))->second
<< lMap.find(tKey('b','c'))->second;

return 0;
}
Jul 22 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Pierre Barbier de Reuille | last post by:
Ok, I first want to stress that I looked through the newsgroups archives (on Google) for an answer to my question, but I didn't find it. It's about the interface of the set classes as defined in...
2
by: mosfets | last post by:
Hi, I'm having a little trouble figuring out the difference in terms of memory allocation between: class person_info; class A { private:
6
by: James Egan | last post by:
I've seen some networking toolkits for C++, but was wondering if there were (or plans for) a standard set of networking classes for C++? Also, can someone tell me where I can find a...
43
by: Steven T. Hatton | last post by:
Now that I have a better grasp of the scope and capabilities of the C++ Standard Library, I understand that products such as Qt actually provide much of the same functionality through their own...
9
by: sakitah | last post by:
Here is what I have: struct SubList { int BookId; int WFreq; }; struct Listing {
1
by: Paul | last post by:
I have a number of MS databases (MDBs). I have written a program that will loop through each database and get information from it. I was able to get the information I needed of all queries within...
3
by: ricky_casson | last post by:
I'm attempting to create a managed C++ class from some an already existing application that I have however some of the classes allow private access via the 'friend' keyword and i've heard that this...
23
by: sidney | last post by:
Hi all, I am trying to make a vector containing objects the have a reference member. However, as soon as I try to push_back an element into this vector, g++ balks at the fact that it needs to...
7
by: ademirzanetti | last post by:
Hi there !!! I would like to listen your opinions about inherit from a STL class like list. For example, do you think it is a good approach if I inherit from list to create something like...
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
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

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.