Pointers from References

G

Govindan

Michael B. Allen said:
I need to create 1000's of objects that reference only a handful of strings.
Rather than allocate space for each redundant string I reasoned this string
member should just be a pointer to one of these handful of strings. The
question is; where to put the handful of strings? For that I decided a
static map and the below function would do the trick (pardon the MFC):

static CMap<CString,CString,CString,CString> strmap;
...
CString *CTest::GetStringPointer(CString& s)
{
if (strmap.Lookup(s, ?)) {
return ?;
}
strmap.SetAt(s, CString( s ));
return ?;
}

As you can see this is incomplete. For each string encountered I want to
look it up in the map. If it exists I return a pointer to it. If it does not
exist in the map I create a new string, add it to the map, and return a
pointer to it. I know passing the string by reference is a good idea and
returning the pointer is my objective but I cant use a CString on the stack
or the pointer returned will be invalid after the call completes.

So how do I get a *pointer* to the element in the map?

Thanks,
Mike

Use the STL , look at a hashmap implementation, use iterators rather than
pointers directly.
 
P

Peter van Merkerk

Michael B. Allen said:
I need to create 1000's of objects that reference only a handful of strings.
Rather than allocate space for each redundant string I reasoned this string
member should just be a pointer to one of these handful of strings. The
question is; where to put the handful of strings? For that I decided a
static map and the below function would do the trick (pardon the MFC):

static CMap<CString,CString,CString,CString> strmap;

Neither CMap nor CString are part of standard C++. You are more likely
to get a good peer reviewed answer if you post this question to a
newsgroup with mfc in its name, such as
news://comp.os.ms-windows.programmer.tools.mfc and
news://microsoft.public.vc.mfc . See also:
http://www.slack.net/~shiva/welcome.txt and
http://home.wanadoo.nl/efx/c++-faq/.
...
CString *CTest::GetStringPointer(CString& s)
{
if (strmap.Lookup(s, ?)) {
return ?;
}
strmap.SetAt(s, CString( s ));
return ?;
}

As you can see this is incomplete. For each string encountered I want to
look it up in the map. If it exists I return a pointer to it. If it does not
exist in the map I create a new string, add it to the map, and return a
pointer to it.

Looking at this description I think you are better of replacing CMap
with std::map, which is not only standard, but also implements the
behaviour you are looking for. If the code is not strictly UI related,
you might also want to consider replacing CString with std::string. Use
standard classes when you (reasonably) can, use non-standard classes
when you have to.
 
C

Christoph Rabel

Michael said:
I need to create 1000's of objects that reference only a handful of strings.
Rather than allocate space for each redundant string I reasoned this string
member should just be a pointer to one of these handful of strings. The
question is; where to put the handful of strings? For that I decided a
static map and the below function would do the trick (pardon the MFC):
static CMap<CString,CString,CString,CString> strmap;

Your use of CMap and CString is offtopic here, better ask this in a
Microsoft NG.

mfg

Christoph
 
M

Michael B. Allen

I need to create 1000's of objects that reference only a handful of strings.
Rather than allocate space for each redundant string I reasoned this string
member should just be a pointer to one of these handful of strings. The
question is; where to put the handful of strings? For that I decided a
static map and the below function would do the trick (pardon the MFC):

static CMap<CString,CString,CString,CString> strmap;
....
CString *CTest::GetStringPointer(CString& s)
{
if (strmap.Lookup(s, ?)) {
return ?;
}
strmap.SetAt(s, CString( s ));
return ?;
}

As you can see this is incomplete. For each string encountered I want to
look it up in the map. If it exists I return a pointer to it. If it does not
exist in the map I create a new string, add it to the map, and return a
pointer to it. I know passing the string by reference is a good idea and
returning the pointer is my objective but I cant use a CString on the stack
or the pointer returned will be invalid after the call completes.

So how do I get a *pointer* to the element in the map?

Thanks,
Mike
 
H

Howard

Christoph Rabel said:
Your use of CMap and CString is offtopic here, better ask this in a
Microsoft NG.

mfg

Christoph

Geez, folks...just because someone uses classes that are defined in MFC,
that doesn't make the question off-topic. What if those were simply
user-defined classes, like MyMap and MyString? Would that be off-topic?
Sure, you may need more info on the behavior of MyMap (or CMap in this
case), but it's still a valid C++ language question.

The OP's problem is how to return a reference or pointer to a member of a
collection, possibly while adding that as a new member first. A perfectly
legitimate question, and other responders have provided helpful info, such
as using iterators instead.

Let's not be so quick to jump on anyone who uses a class that just happens
to be written by Microsoft, ok? They're not *totally* evil! :)

-Howard
 
I

Ivan Vecerina

Hi Michael,
What I meant was:
CString* CTest::GetStringPointer(CString& s)
Mmm, I take it one of these returns a reference to a pointer and the other
returns a reference to the object in the map? Is the & in the return
statement in the first example the address-of operator or is that some way
to get a reference to something? If the later is true why is it necessary
for return values when it isn't necessary for parameters?
It was a plain address-of operator, to obtain a pointer from a reference.
Is this the method being used?

pair<iterator, bool> insert(const value_type& x)
Yes, exactly.
How is 'iterator' defined?
Iterators are objects that behave very much like pointers: they refer to
an object within a collection (rather than a contiguous array). They
support a similar set of operations ( * and -> to access the item,
++ or -- to move to the next/previous item, etc ).
Each C++ collection defines an iterator (and a const_iterator), providing
a way to traverse its items.

BTW, the function could return an iterator instead of a pointer or
reference -- but this would expose an implementation detail (that is,
users of the function would have to specifically use
std::set<CString>::iterator instead of CString& or CString*.
And because users don't need to see the previous or next item,
there is no benefit in returning an iterator.
This is why the functions dereference the iterator to obtain
a reference (or the address of) the item itself.

They reason why I would return a reference (CString&) instead of
a pointer (CString*) is that the reference indicates that a
valid object is always returned -- while the pointer suggests
that NULL could be returned. This is a style choice.
I just realized, here I go again, I'm learning a new language!
Do you think I can put this on my resume yet ;->
Well, just another library ... but a standard one, which BTW
can be quite powerful.


Cheers,
Ivan
 
M

Michael B. Allen

The behavior you want would easily be implemented with
the std::set collection, rather than a map:

Yes. I see.
static std::set<CString> strset;

CString& CTest::GetStringPointer(CString& s)
{
return & * strset.insert(s).first;
}

Or better IMHO:

CString& CTest::GetStringReference(CString& s)
{
return * strset.insert(s).first;
}

Mmm, I take it one of these returns a reference to a pointer and the other
returns a reference to the object in the map? Is the & in the return
statement in the first example the address-of operator or is that some way
to get a reference to something? If the later is true why is it necessary
for return values when it isn't necessary for parameters?

Is this the method being used?

pair<iterator, bool> insert(const value_type& x)

How is 'iterator' defined?

I just realized, here I go again, I'm learning a new language! Do you think
I can put this on my resume yet ;->

Mike
 

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

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top