473,387 Members | 3,821 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,387 software developers and data experts.

Returning a STL Map Object

I am an STL newbie trying to build a class DUTBus that has a map
object. In my member function, I try to return a Map Object, however,
it does not seem to work. I am referring to "Bus getBus()"
function.

I need to do this because in order to "add" device pins (via
registerPin() function. In other words, I need to modify the map by
inserting new (key,value) pairs into the object. However, when I try to
access the bus object by returning it, it doesnt work!

Please help!

Thanks
Anand

#include <string>
typedef map<int, string> Bus;
typedef Bus::iterator BusIterator;

class DUTBus
{
private:
Bus _bus;
public:
DUTBus() { }
Bus getBus();
inline int getBusSize() { return (_bus.size()); }
void registerPin(int, string);

};
Bus DUTBus::getBus()
{
return(_bus);
}

void DUTBus::registerPin(int _idx, string _pin)
{
Bus myBus = this->getBus();
BusIterator iter;
iter = myBus.begin();
myBus.insert(pair<int, string>(_idx,_pin));
cout << "Inserted Bus[" << _idx << "]\t=\t" << _pin;
}


main(void)
{
Bus myBus;
DUTBus* DataBus = new DUTBus();
DataBus->registerPin(1,"T_x_p_ad1");
DataBus->registerPin(2,"T_x_p_ad2");
DataBus->registerPin(3,"T_x_p_ad3");

myBus = DataBus->getBus();
cout << "This bus has a size of " << myBus.getBusSize() << endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #1
11 2195
"anand" <wr********@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
I am an STL newbie trying to build a class DUTBus that has a map
object. In my member function, I try to return a Map Object, however,
it does not seem to work. I am referring to "Bus getBus()"
function.

I need to do this because in order to "add" device pins (via
registerPin() function. In other words, I need to modify the map by
inserting new (key,value) pairs into the object. However, when I try to
access the bus object by returning it, it doesnt work!

Please help!

Thanks
Anand

#include <string>
typedef map<int, string> Bus;
typedef Bus::iterator BusIterator;

class DUTBus
{
private:
Bus _bus; NB: Leading underscores are best avoided in identifier names
(they are reserved for the implementation in some contexts).
Trailing underscores (bus_) are therefore usually preferred.
public:
DUTBus() { }
Bus getBus(); Problem: In C++, this returns a (deep) copy of the stored _bus
object. If you want to return an object reference, you need to
do so explicitly:
Bus& getBus() { return _bus; }
However, the latter defeats the purpose of having a private
data member, and is therefore best avoided.
A sometimes useful alternative, which still allows the class to
control its invariants, is:
Bus const& getBus() const { return _bus; }
inline int getBusSize() { return (_bus.size()); } NB: inline is redundant here, and a 'const' would be better:
int getBusSize() const { return (_bus.size()); }
void registerPin(int, string);

};
Bus DUTBus::getBus()
{
return(_bus);
}

void DUTBus::registerPin(int _idx, string _pin)\ Again, leading underscores are best avoided. And it is
a quite uncommon C++ style to use them in this context.
{
Bus myBus = this->getBus(); This creates a local copy of the _bus object. That local
copy is then modified, and destroyed, while the _bus data
member remains unchanged. ***this is what causes your 'bug'***
Use the _bus data member direcly. Or if you want a local
reference to the data member, use:
Bus& myBus = _bus;
BusIterator iter;
iter = myBus.begin(); Prefer combining declaration and instanciation:
BusIterator const iter = myBus.begin();
But anyway, 'iter' is not needed in this function.
myBus.insert(pair<int, string>(_idx,_pin));
cout << "Inserted Bus[" << _idx << "]\t=\t" << _pin;
} The function will work correctly if you replace its body with:
_bus.insert( pair<int, string>(_idx,_pin) );
Or even easier, since you don't seem to care about wheter a pin
with the same number already existed:
_bus[_idx] = _pin;
main(void)
{
Bus myBus; It is better to declare local variables on first use... DUTBus* DataBus = new DUTBus(); Don't allocate objects on the heap unless it is necessary. Just use:
DUTBus DataBus; DataBus->registerPin(1,"T_x_p_ad1");
DataBus->registerPin(2,"T_x_p_ad2");
DataBus->registerPin(3,"T_x_p_ad3");

myBus = DataBus->getBus(); This again creates a local *copy* of the DataBus->_bus , which
may not be what you want (although it will work ok in this context).
cout << "This bus has a size of " << myBus.getBusSize() << endl;
}


I hope this helps. Note that it might be a good idea to spend more time
studying C++ before trying to write more complex programs...
Regards, Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #2
You're confusing a Bus with a DUTBus, and the insertions don't work
because you're inserting into a local copy of _bus, not _bus itself.
Also, don't forget to include the requisite headers and qualify for the
std namespace:

#include <iostream>
#include <map>
#include <utility>
#include <string>

typedef std::map<int, std::string> Bus;
typedef Bus::iterator BusIterator;

class DUTBus
{
private:
Bus _bus;
public:
Bus getBus();
inline int getBusSize() { return (_bus.size()); }
void registerPin(int, std::string);
};

Bus DUTBus::getBus()
{
return(_bus);
}

void DUTBus::registerPin(int _idx, std::string _pin)
{
_bus.insert(std::pair<int, std::string>(_idx,_pin));
std::cout << "Inserted Bus[" << _idx << "]\t=\t" << _pin;
}

int main(void)
{
Bus myBus;
DUTBus* DataBus = new DUTBus();

DataBus->registerPin(1,"T_x_p_ad1");
DataBus->registerPin(2,"T_x_p_ad2");
DataBus->registerPin(3,"T_x_p_ad3");

myBus = DataBus->getBus();
std::cout << "This bus has a size of " << myBus.size() << std::endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #3
> I try to return a Map Object, however, it does not seem to work.
Could you please be a bit more specific about what doesn't work?
Compile time error? Unexpected runtime behavior?

As far as I can tell the only thing wrong with the above code is the
line:
cout << "This bus has a size of " << myBus.getBusSize() << endl;
.. You are calling getBusSize() on an object of type Bus. Type Bus is
really a map<int, string> and, of course, does not have a member
function getBusSize().
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #4
The problem is that during every iteration of registerPin(),
you are calling your getBus() function, which returns a copy
of your Bus map object.
Your insert operation acts on this copy, which is then lost
when the registerPin() function finishes.

So, to fix - change your registerPin() function so that it
directly inserts on the contained Bus object instead.

#include <string>
#include <iostream>
#include <map>

class DUTBus {
public:
typedef std::map<int, std::string> Bus;

const Bus& getBus() const { return bus; }

Bus::size_type getBusSize() const { return bus.size(); }

void registerPin(int index, const std::string& pin) {
bus.insert(std::make_pair(index, pin));
}

private:
Bus bus;
};

int main() {
DUTBus dataBus;
dataBus.registerPin(1, "T_x_p_ad1");
dataBus.registerPin(2, "T_x_p_ad2");
dataBus.registerPin(3, "T_x_p_ad3");

const DUTBus::Bus& myBus = dataBus.getBus();

std::cout << "This bus has a size of " << myBus.size() << std::endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #5
You are basically saying that dont declare a local DataBus since it is
redundant and wastes memory...Hope I got it right!

-Anand
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #6
> > public:
DUTBus() { }
Bus getBus();

Problem: In C++, this returns a (deep) copy of the stored _bus
object.


I don't think this is true. It returns a copy by calling the copy
constructor. If one is not implemented, it calls the compiler
generated default copy constructor which is *NOT* a deep copy.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #7
"Anand" <wr********@gmail.com> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
You are basically saying that dont declare a local DataBus since it is
redundant and wastes memory...Hope I got it right!

Nearly yes.
The key thing is that you need to understand better the C++ object
model: read about object constructors, copy-constructors, and
assignment operators; understand what references and pointers
mean in C++.
I would recommend "Accelerated C++" as a book [by Austern & Moo],
of if you are looking for something that is also available online
for free, Thinking in C++, by Bruce Eckel.

{Moderator's note: "Accelerated C++" is by Andrew Koenig and Barbara
Moo, not by Matt Austern; Matt's book is "Generic Programming and the STL".
-dk/mod}

Cheers,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #8
BigBrian wrote:
public:
DUTBus() { }
Bus getBus();
Problem: In C++, this returns a (deep) copy of the stored
_bus object.
I don't think this is true. It returns a copy by calling the
copy constructor. If one is not implemented, it calls the
compiler generated default copy constructor which is *NOT* a
deep copy.


But in this case, one is implemented, and it has deep copy
semantics. (Bus is a typedef to an instantiation of std::map.)

In general, deep copy is idiomatic C++, and except in special
cases, you should either ensure deep copy, or ban copy, in your
own classes. And the compiler generated copy constructor is
member-wise copy -- if all of the members implement deep copy,
it is effectively deep copy. (Of course, C++ raw pointers do
NOT have deep copy semantics. And the presence of a raw pointer
in a class is frequently a sort of a danger flag that says you
need a user defined copy contructor.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #9
Anand wrote:
You are basically saying that dont declare a local DataBus
since it is redundant and wastes memory...Hope I got it right!


No. He's saying not to declare a local DataBus because it is a
separate object. Modifying it does not change anything in the
DataBus object it was created from.

Redundancy and wasting memory are optimization issues. In the
case of containers, you can't necessarily ignore them, but the
issue here is a more serious one of correctness: using deep copy
semantics when you need reference semantics.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #10
"BigBrian" <wo**@brianmielke.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
> public:
> DUTBus() { }
> Bus getBus();

Problem: In C++, this returns a (deep) copy of the stored _bus
object.


I don't think this is true. It returns a copy by calling the copy
constructor. If one is not implemented, it calls the compiler
generated default copy constructor which is *NOT* a deep copy.


I added this '(deep)' qualification only to clearly oppose
this case to what happens in Java and other languages, where an
object is "copied" by just creating a new reference/pointer to it.

Furthermore, given that 'Bus' was defined as:
typedef map<int, string> Bus;
the copy of the object is as deep as it can be: each std::pair
and std::string object stored will be copied to a new instance
and address.

Cheers,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #11
BigBrian wrote:
public:
DUTBus() { }
Bus getBus();
Problem: In C++, this returns a (deep) copy of the stored _bus
object.

I don't think this is true. It returns a copy by calling the copy
constructor. If one is not implemented, it calls the compiler
generated default copy constructor which is *NOT* a deep copy.

You are correct, this is not a "deep" copy. Try storing pointers
to objects in your map and see how well it does a deep copy. All it
will copy is the address of each element in the map... the result is
two maps that both point to the same elements on the heap. A
modification in one map will affect the other. This is not deep copy
semantics.

Kyle

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 23 '05 #12

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

Similar topics

9
by: mjm | last post by:
Folks, Stroustrup indicates that returning by value can be faster than returning by reference but gives no details as to the size of the returned object up to which this holds. My question is...
7
by: Pablo J Royo | last post by:
Hello: i have a function that reads a file as an argument and returns a reference to an object that contains some information obtained from the file: FData &ReadFile(string FilePath); But ,...
12
by: Olumide | last post by:
I'm studying Nigel Chapman's Late Night Guide to C++ which I think is an absolutely fantastic book; however on page 175 (topic: operator overlaoding), there the following code snippet: inline...
11
by: JKop | last post by:
AnyClass Blah() { AnyClass poo; return poo; } As we all know, in the above, the compiler is entitled to:
8
by: briforge | last post by:
I am writing a program for the Palm OS in c++. I have already posted this to a palm development forum but I'm desperate for a fix, so I hope this cross-post isn't offensive. My program is...
3
by: Faustino Dina | last post by:
Hi, The following code is from an article published in Informit.com at http://www.informit.com/guides/content.asp?g=dotnet&seqNum=142. The problem is the author says it is not a good idea to...
23
by: pauldepstein | last post by:
Below is posted from a link for Stanford students in computer science. QUOTE BEGINS HERE Because of the risk of misuse, some experts recommend never returning a reference from a function or...
8
by: darren | last post by:
Hi everybody, have a quick look at this code: ===== ===== int main(void) { string msg; makeString(msg); cout << "back in main, result = " << msg << endl;
160
by: DiAvOl | last post by:
Hello everyone, Please take a look at the following code: #include <stdio.h> typedef struct person { char name; int age; } Person;
5
by: ctj951 | last post by:
I have a very specific question about a language issue that I was hoping to get an answer to. If you allocate a structure that contains an array as a local variable inside a function and return...
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: 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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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:
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...

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.